spring事务管理&transactional实战
spring framework对事务管理提供了一致的抽象
-为不同的事务API提供了一致的编程模型
-支持声明式事务,特别是基于注解的声明式事务管理,简单易用
-提供其他事务API更简单的事务管理API
-与spring数据访问完美集成
事务管理支持编程式事务管理和声明式事务管理
编程式事务管理你使用trasactionTemplate或直接用PlatformTrasactionManager,spring推荐使用前者
声明式事务建立在AOP之上,其本质是对方法前后进行拦截,在目标方法前创建或加入一个事务,执行完后根据执行情况提交或回滚事务(非侵入式的开发方式,和前者相比,不足之处是最细粒度只能作用到方法级别,无法像编程式事务那样作用到代码块级别)
自动提交与连接关闭时是否自动提交
默认情况下,数据处于自动提交模式,每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。
对于正常的事务,是一组相关操作处以一个事务中,因此必须关闭自动数据库的自动提交模式(spring设置自动提交模式为false)
连接关闭,默认不自定提交,回滚
声明式事务管理
一种是基于tx和aop名字空间的xml配置文件(和参数校验的AOP类似),另一种是基于@Transactional注解
特性: 事务隔离级别,事务的传播行为,事务超时,事务只读属性,事务回滚规则
隔离级别:读未提交-脏读;读已提交-不可重复读;可重复读-幻读;序列化
传播行为:存在事务,加入,不存在创建;存在事务,挂起,创建事务;不存在事务,抛异常;存在事务,加入,不存在,则以非事务方式运行;存在事务,创建嵌套事务,不存在事务,创建事务;存在事务,抛异常;存在事务,挂起,以非事务方式运行;
annotation-driven 开启了注解事务。
默认情况会自动使用名称为transactionManager的事务管理器,所以定义的事务管理名称为transactionManager,就可以直接使用<tx:annotation-driven/>
-transactional注解可以标注在类和方法上, 也可以标注在接口和接口方法上;
-如果将transactional标注到接口上,会存在隐患: 注解不能被继承,所以业务接口中标的注解不会被业务实现类继承,可能出现不启动事务的情况。所以spring建议将transactional注解在实现类上
-在方法上的transactional会覆盖掉类上的transactional
在一个工程中可以有多个事务管理器(主要是针对多数据源的情况)
<tx:annotation-driven/>只会查找和它在相同的应用上下文中定义的bean上的@Transactional注解(没有尝试)
参考:
tx:annotation-driven注解:https://blog.csdn.net/jackyechina/article/details/53097915
tx:annotation-driven标签解析过程: https://blog.csdn.net/lyc_liyanchao/article/details/85136453
tx:annotation-drviven理解:https://www.cnblogs.com/alice-cj/p/10417773.html
声明式事务管理方式:https://www.cnblogs.com/niceyoo/p/8732891.html
spring、mybatis事务管理配置: https://www.cnblogs.com/xusir/p/3650522.html
transactional实战
xml配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath*:mybatis-mappers/*.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.acc.quota.pool.mappers" /> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- enable transaction annotation support --> <tx:annotation-driven transaction-manager="txManager" /> </beans>
报错
Caused by: java.lang.ClassNotFoundException: org.springframework.context.event.EventListenerFactory
原因: spring包依赖版本太混乱,尤其spring-tx,将spring-tx的的隐式依赖,改为显式依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.1.7.RELEASE</version> </dependency> <!-- org.aspectj.lang.annotation.Around --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.10.1.RELEASE</version> <exclusions> <exclusion> <artifactId>spring-data-commons</artifactId> <groupId>org.springframework.data</groupId> </exclusion> <exclusion> <artifactId>spring-tx</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency>
@Transactional注解底层使用的是动态代理来进行实现的,如果在调用本类中的方法,此时不添加@Transactional注解,而是在调用类中使用this调用本类中的另外一个添加了@Transactional注解,此时this调用的方法上的@Transactional注解是不起作用的。
默认情况下: 事务隔离级别: 读提交; 事务传播方式: 存在事务,加入,不存在,创建事务;
参考:
Spring之@Transactional注解原理: https://www.cnblogs.com/superheroJC/p/10715353.html