Spring的事务管理
事务
逻辑上的一组操作,要不全部成功,要不全部失败。
- 原子性
- 隔离性
- 一致性
- 几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
- 持久性
在没有事务导致的问题
- 读问题
- 脏读
- 读到了未提交的数据
- 虚读
- 读到了其他事务提交的数据,导致两次查询结果集数量不同
- 不可重复读
- 读到了其他事务提交的数据,导致统一条记录,两次查询结果不同
- 脏读
- 写问题
- 丢失更新
解决方法
- 读问题 通过设置事务的隔离级别解决。
- 写问题 通过乐观锁、悲观锁解决。
Spring的事务管理的API
- PlatformTransactionManager 事务管理器
- TransactionDefinition 事务隔离级别、传播策略
- TransactionStatus 事务状态
- 关系:平台事务管理器真正管理事务对象.根据事务定义的信息TransactionDefinition.进行事务管理.在管理事务中产生一些状态.将状态记录到TransactionStatus中.
事务管理器常见的实现类(与使用的数据库连接池有关)
- DataSourceTrsansactionManager (Spring JDBC 或 Mybatis)
- HibernateTransactionManager (Hibernate)
JpaTransactionManager (JPA)
- 顶层接口方法
- getTransaction(TransactionDefinition)
- commit(TransactionStatus)
- rollback(TransactionStatus)
事务定义
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package org.springframework.transaction;
public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
java.lang.String getName();
}
ISOLATION_* :事务隔离级别
- ISOLATION_DEFAUTL :
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIZABLE
PROPAGATION_*: 事务传播行为:A、B为使用 同一个数据库连接的方法。
- PROPAGATION_REQUIRED :A中有事务,使用A中的事务.如果没有B就会开启一个新的事务,将A包含进来.(保证A,B在一个事务中)
- PROPAGATION_SUPPORTS :A中有事务,使用A中的事务.如果A中没有事务.那么B也不使用事务.
PROPAGATION_MANDATORY :A中有事务,使用A中的事务.如果A没有事务.抛出异常.
PROPAGATION_REQUIRES_NEW :A中有事务,将A中的事务挂起.创建一个新的事务.(保证A,B没有在一个事务中)
- PROPAGATION_NOT_SUPPORTED :A中有事务,将A中的事务挂起.
PROPAGATION_NEVER :A中有事务,抛出异常.
PROPAGATION_NESTED :嵌套事务.当A执行之后,就会在这个位置设置一个保存点.如果B没有问题.执行通过.如果B出现异常,运行客户根据需求回滚(选择回滚到保存点或者是最初始状态)
TransactionStatus 事务的状态
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
Spring 事务配置(编程式事务)
不做赘述,了解即可(很少使用)
Spring为了简化事务管理的代码:提供了模板类.TransactionTemplate.
步骤一:配置一个事务管理器.
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
步骤二:配置事务管理的模板:
<!-- 配置事务管理的模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
步骤三:在需要进行事务管理的类中,注入事务管理的模板.
<!-- 配置业务层的类 -->
<bean id="accountService" class="com.itheima.spring.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<!-- 注入事务管理的模板 -->
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
步骤四:在业务层使用模板管理事务:
@Override
public void transfer(final String out, final String in, final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.outMoney(out, money);
int d = 1 / 0;
accountDao.inMoney(in, money);
}
});
}
Spring 事务配置 (声明式事务 使用AOP实现)
- Spring 通过ProxyFactoryBean 实现自动代理
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置生成代理:增强业务层类 -->
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置目标类 -->
<property name="target" ref="accountService"/>
<!-- 注入事务管理器 -->
<property name="transactionManager" ref="transactionManager"/>
<!-- 配置事务的相关属性 -->
<property name="transactionAttributes">
<!-- prop格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception -->
<props>
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
- 通过 AspectJ 实现代理(重点掌握)
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务增强 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
propagation :传播行为
isolation :隔离级别
read-only :是否只读
timeout :超时信息
rollback-for:发生哪些异常回滚.
no-rollback-for:发生哪些异常不回滚.
-->
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置AOP切面产生代理 -->
<aop:config>
<aop:pointcut expression="execution(* com.itheima.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>