Transactional介绍及使用

 

1、在xml文件中加入事务管理器

class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
   
   
   
   
   
   
   
   
   
   


class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   
   
   
   
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
         
         
      
   
   
      
         ${hibernate.dialect}
         org.hibernate.cfg.ImprovedNamingStrategy
         ${hibernate.cache.use_second_level_cache}
         ${hibernate.cache.region.factory_class}
         ${hibernate.cache.use_query_cache}
         ${hibernate.jdbc.fetch_size}
         ${hibernate.jdbc.batch_size}
         2
         none
         filesystem
         ${java.io.tmpdir}/${system.project_name}/index
         false
         true
         false
         update
         true
      
   


class="org.springframework.orm.jpa.JpaTransactionManager">
   


2、在类上或者方法上加入@Transactional
标注在类前:标示类中所有方法都进行事务处理
标注在接口、实现类的方法前:标示方法进行事务处理

事务传播行为:

@Transactional(propagation=Propagation.REQUIRED) 如果有事务, 那么加入事务, 没有的话新建一个(默认情况)
@Transactional(propagation=Propagation.NOT_SUPPORTED) 容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW) 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY) 必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER) 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务。如果其他bean没有声明事务,那就不用事务

事务隔离级别:

@Transactional(isolation = Isolation.READ_UNCOMMITTED) 读取未提交数据(会出现脏读, 不可重复读),基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER默认) 读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ) 可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE) 串行化

 

由于Spring事务管理是基于接口代理或者动态字节码技术,通过AOP实施事务增强的。基于接口动态代理的AOP事务增强来说,由于接口的方法是public的,这句要求实现类的实现方法必须是public 的(不能是protect,private等),同时不能使用static的修饰符。所以可以实施接口动态代理的方法也只能是“public”或者“public fianl ” 其他方法不可能被动态代理,相应的也就不能实施AOP增强,也无法进行Spring事务增强。

@Transactional 注解标识的方法,处理过程尽量的简单。尤其是带锁的事务方法,能不放在事务里面的最好不要放在事务里面。可以将常规的数据库查询操作放在事务前面进行,而事务内进行增、删、改、加锁查询等操作。


原理:
运行配置@Transactional注解的测试类的时候,具体会发生如下步骤
1)事务开始时,通过AOP机制,生成一个代理connection对象,并将其放入DataSource实例的某个与DataSourceTransactionManager相关的某处容器中。在接下来的整个事务中,客户代码都应该使用该connection连接数据库,执行所有数据库命令[不使用该connection连接数据库执行的数据库命令,在本事务回滚的时候得不到回滚]
2)事务结束时,回滚在第1步骤中得到的代理connection对象上执行的数据库命令,然后关闭该代理connection对象

根据上面所述,我们所使用的客户代码应该具有如下能力:
1)每次执行数据库命令的时候
如果在事务的上下文环境中,那么不直接创建新的connection对象,而是尝试从DataSource实例的某个与DataSourceTransactionManager相关的某处容器中获取connection对象;在非事务的上下文环境中,直接创建新的connection对象
2)每次执行完数据库命令的时候
如果在事务的上下文环境中,那么不直接关闭connection对象,因为在整个事务中都需要使用该connection对象,而只是释放本次数据库命令对该connection对象的持有;在非事务的上下文环境中,直接关闭该connection对象

你可能感兴趣的:(Transactional介绍及使用)