Spring 声明式事务
一 Spring的事务
Spring的事务控制可以分为编程式事务控制和声明式事务控制(aop)。
编程式
开发者直接把事务的代码和业务代码耦合到一起,在实际开发中不用。
声明式
开发者采用配置的方式来实现的事务控制,业务代码与事务代码实现解耦合,使用的AOP思想。
1.1 编程式事务【了解】
spring提供了操作事务的api,让开发者可以去使用提供好的api开发使用事务
1)PlatformTransactionManager–事务管理器
是spring事务管理器核心接口,定义了事务的操作规范
实现类
* DataSourceTransactionManager---重点
spring提供给jdbcTemplate和mybatis以及dbutils使用
* HibernateTransactionManager
spring提供给hibernate适用
* JpaTransactionManager
spring提供给Jpa适用
2)TransactionDefinition
是spring提供设置相关信息的定义对象
1 定义事务的隔离级别
isolation=默认值 (随着数据库的隔离级别而变化)
2 定义事务的超时时间
timout=-1 (什么时候执行完毕什么时候结束)
3 定义事务是否只读行为
增删改语句 readonly=false 开事务(默认)
查询语句: readonly=true 关闭事务 提高查询效率
4 定义事务的传播行为
propagation=REQUIRED
propagation=SUPPORTS
1 事务隔离级别:如果没有隔离级别容易出现一些读取问题
- read_uncommited:(读未提交)会出现脏读
- read_committed:(读已提交)可以解决脏读,会出现不可重复读
- repeatable_read:(可重复读)可以解决不可重复读 【mysql默认】
- serializable:(串行化)可以解决一切
定义隔离级别方式
isolation取值如下:
2 等待超时
- timout
默认值为-1,永不超时,我们可以指定超时时间单位秒
3 是否只读
- readonly
我们在执行DML语句,设置false
执行DQL语句,设置true,默认值 false
一旦设置为true,表示不会开启事务,提高查询效率
增删改语句 readonly=false 开事务(默认)
查询语句: readonly=true 关闭事务 提高查询效率
4 事务传播行为
多方法嵌套调用的时候,被调用方法对事务的支持情况
A方法
B方法
-propagation
- REQUIRED(保证必须有事务)
被调用者会看调用者是否有事务,如果有事务直接加入,如果没事务,创建一个事务
保证多个方法在一个事务中
- SUPPORTS(可有可无事务)
被调用者会看调用者是否有事务,如果有事务直接加入,如果没事务,就使用非事务一起执行
1.2 声明式事务【重点】
在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。底层采用AOP思想来实现的
1) xml配置
快速入门
1 将spring事务管理器交给spring容器管理
2 配置事务特性
3 配置事务AOP的织入过程
详解
<!--1 将spring的事务管理器(通知)放入ioc容器中-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druid"></property>
</bean>
<!--2 设置事务特性 类似TransactionDefinition
<tx>
-->
<tx:advice id="Myadvice" transaction-manager="transactionManager">
<tx:attributes>
<!--给指定方法配置事务管理器中事务的特性-->
<tx:method name="tranFer" isolation="DEFAULT" timeout="-1" read-only="false" propagation="REQUIRED"/>
<!-- <tx:method name="find*" isolation="DEFAULT" timeout="-1" read-only="true" propagation="SUPPORTS"/>
<tx:method name="*" isolation="DEFAULT" timeout="-1" read-only="true" propagation="SUPPORTS"/>-->
</tx:attributes>
</tx:advice>
<!--3 aop做事务织入-->
<aop:config>
<aop:pointcut id="pt" expression="execution(* cn.itcast.serviceimpl.AccountServiceImpl.tranFer(..))"></aop:pointcut>
<aop:advisor advice-ref="Myadvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
2)半xml半注解配置
1 开启对注解事务的支持
<!--对事务注解的支持-->
<tx:annotation-driven></tx:annotation-driven>
2 将事务管理器交给spring容器管理
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
3 在需要事务的类或者方法上使用@Transactional注解配置事务
/**
* 配置事务
* @Transactional
* 配置到类上 :表明此类中的所有方法都具有此事务
* 配置到方法上 :表明此方法具有此事务
* * 就近原则(方法上的配置会覆盖类上的配置)
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional(isolation = Isolation.DEFAULT,timeout =-1,readOnly = false,propagation = Propagation.REQUIRED)
public void tranFer() {
accountDao.toMoney();
int i=1/0;
accountDao.inMoney();
}
}