方式一、使用AOP配置提供事务增强
在spring配置中增加如下配置
<!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" /> <!-- 通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务 --> <aop:config proxy-target-class="true"> <aop:pointcut id="serviceMethod" expression=" execution(* com.future.service..*(..)) or execution(* com.future.controller..*(..))" /> <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" /> <!--以下注释部分可以提供更细致的回滚策略--> <!--<tx:method name="insert*" rollback-for="Exception" /> <tx:method name="save*" rollback-for="Exception" /> <tx:method name="update*" rollback-for="Exception" /> <tx:method name="delete*" rollback-for="Exception" /> <tx:method name="*" read-only="true" rollback-for="Exception" />--> </tx:attributes> </tx:advice>
其中p:dataSource-ref="dataSource"中的为数据源的bean id
<!-- 配置数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${driver}" p:url="${url}" p:username="${username}" p:password="${password}" p:initialSize="${initialSize}" p:maxActive="${maxActive}" p:maxIdle="${maxIdle}" p:minIdle="${minIdle}" p:maxWait="${maxWait}" />
这样在service包下的Mapper接口的实现类里的所有方法就具备了事务能力(有点粗放,可以精确到具体的方法)。
方式二、编程式事务管理
主要参考:http://blog.youkuaiyun.com/ymh198816/article/details/43187747
使用Spring的事务管理器去管理事务,通过ptm.commit(status);去手动提交事务。
@Repository(value = "annotationUserService")
public class AnnotationUserService implements UserMapper {
@Autowired
private IUserDao userDao;
@Autowired
private PlatformTransactionManager ptm;
private static Logger LOGGER = LogManager.getLogger(AnnotationUserService.class);
@Transactional
public int insertDefault(User record) {
this.userDao.insertDefault(record);
return 1;
}
public int insertTwice(User record) {
LOGGER.info("PlatformTransactionManager:{}", ptm);
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = ptm.getTransaction(def);
try{
this.userDao.insertDefault(record);
this.userDao.insert(record);
ptm.commit(status);
} catch (Exception e) {
ptm.rollback(status);
e.printStackTrace();
}
return 1;
}
}
方式三、使用@Trasactional注解
可以在类名上使用该注解, 则类中全部方法具有事务能力。也可以对单个方法使用该注解。注解可以使用各种参数,主要参考下图。
属性 | 类型 | 描述 |
---|---|---|
value | String | 可选的限定描述符,指定使用的事务管理器 |
propagation | enum: Propagation | 可选的事务传播行为设置 |
isolation | enum: Isolation | 可选的事务隔离级别设置 |
readOnly | boolean | 读写或只读事务,默认读写 |
timeout | int (in seconds granularity) | 事务超时时间设置 |
rollbackFor | Class对象数组,必须继承自Throwable | 导致事务回滚的异常类数组 |
rollbackForClassName | 类名数组,必须继承自Throwable | 导致事务回滚的异常类名字数组 |
noRollbackFor | Class对象数组,必须继承自Throwable | 不会导致事务回滚的异常类数组 |
noRollbackForClassName | 类名数组,必须继承自Throwable | 不会导致事务回滚的异常类名字数组 |
详解如下(转载)
http://blog.youkuaiyun.com/u014001866/article/details/52817643
1、isolation事务隔离级别
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:
- TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
- TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
- TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
- TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
2、propagation事务传播行为
(1)PROPAGATION_REQUIRED
(2)PROPAGATION_REQUIRES_NEW
(3)PROPAGATION_NESTED
(4)其他
3、timeout事务超时
所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。
默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。
4、readOnly事务只读属性
只读事务用于客户代码只读但不修改数据的情形,只读事务用于特定情景下的优化,比如使用hibernate的时候。
默认为读写事务。
5、spring事务回滚规则
指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。
默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。
可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。
还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。