1:基本原理
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:
1:获取连接 Connection con = DriverManager.getConnection() 2:开启事务con.setAutoCommit(true/false); 3:执行CRUD 4:提交事务/回滚事务 con.commit() / con.rollback(); 5:关闭连接 conn.close();
使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。下面简单地介绍下,注解方式为例子
1:配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。 2:spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。 3:真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
2: @Transactional注解使用警戒线
不允许在private方法上加@Transactional注解,因为即时在private方法上加上该注解Spring事务也不起作用。
如果要使用aspectj方式来进行事务控制,pom文件中需要引入spring-aspects 。
当在同一个类中,一个没注解的方法调用一个有@Transactional方法时,事务不生效 。不管运行期异常是在哪个方法中抛出,事务均不生效(亲测,但仅当使用JDKProxy代理),但是当使用AspectJ时,不影响,AspectJ配置如下:
<!-- Spring生成代理有2种方式,默认使用JDKProxy -->
<tx:annotation-driven transaction-manager="txManager" />
<!--代理模式 基于CGLIB-->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
<!--如果要使用aspectj方式来进行事务控制,pom文件中需要引入spring-aspects-->
<tx:annotation-driven transaction-manager="txManager" mode="aspectj"/>
3. 扩展阅读
http://blog.csdn.net/tzdwsy/article/details/50491459
Spring动态代理的坑
Transaction 那些事儿
spring事务管理的一些注意点
4. 使用SpringJunit4Test进行测试时,@Rollback生效问题:
如果需要@Rollback注解生效,则需要在测试类上加上@Transactional注解,否则@Rollback不起作用。
如果没有整合SpringJunit4Test,则@Rollback可正常生效,默认true。
扩展阅读:示例代码