spring事务有7种传播行为,分别是:
1、PROPAGATION.REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION.SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
3、PROPAGATION.MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION.REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION.NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION.NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION.NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
注解@Transactional默认的传播行为是:PROPAGATION.REQUIRED
若需要设置其他传播行为,设置方法如下:
@Transactional(propagation = Propagation.REQUIRED) public void test() { //... }
上面的设置的作用是:当方法test出现 “运行时异常” 时,会进行事务回滚(其实是伪回滚,只是把之前的操作改回去。比如有插入操作且是主键是自增长的,假设插入一条记录的操作前,下一id的值是1,但伪回滚后,就变成2了,也就是说,下一次成功插入后,id的值是2而不是1)。
但是如果,在test方法的方法体中捕获了异常,则不会对事务进行回滚,代码如下:
@Transactional public void test() { try{ //... } catch(DataAccessException e) { e.printStackTrace(); } }
上边的代码,如果对多个表进行操作,有成功也有失败的操作,但最后,成功的操作不会被回滚,因为异常被捕获了,spring捕获不到,也就没办法回滚了。
要想既捕获异常然后做一些操作,又想对失败的操作进行回滚,可以在捕获异常后,再对异常抛出,即让spring能捕获该异常 ,示例如下:
@Transactional public void test() { try{ //... } catch(DataAccessException e) { e.printStackTrace(); throw e; } }
另外,被@Transactional注解的方法,spring不止对捕获数据访问异常才会进行回滚,而是只要捕获到了运行时异常都会进行回滚,比如下面的示例:
@Transactional public void test() { try{ //... int [] counts = new int[]{1}; int count = counts[1]; } catch(RuntimeException e) { e.printStackTrace(); throw e; } }
上边的代码,会报数组下标越界的“运行时异常” ,但被捕获了,就算之前对数据库的操作是成功的,之前对数据库的操作还是会被回滚。
暂时到这里,以后遇到新问题再补充。