spring_事物
1.事务
1.1 什么是事务:
- 事务(TRANSACTION) 是作为单个逻辑工作单元执行的一系列操作。
- 多个操作作为一个整体向系统提交,要么都执行,要么都不执行。
- 事务是一个不可分割的逻辑单元。
1.2 事务的特性:
事务具备以下四个特性,简称ACID属性。
- 原子性(Atomicity):
- 事务是一个完整的操作,事务的各步操作都是不可再分的,要么都执行,要么都不执行。
- 一致性(Consistency):
- 当事务完成时,数据必须处于一致的状态。
- 隔离性(Isolation):
- 并发事务之间相互独立、隔离,它不应以任何方式依赖于或影响其他事务。
- 持久性(Durability):
- 事务完成后,它对数据库的修改被永久保持。
1.3 mysql 事务操作---简单
ABCD 一个事务 Connection conn = null; try{ //1 获得连接 conn = ...; //2 开启事务 conn.setAutoCommit(false); A B C D //3 提交事务 conn.commit(); } catche(){ //4 回滚事务 conn.rollback(); }
1.4 mysql 事务操作---Savepoint
需求:AB(必须),CD(可选) Connection conn = null; Savepoint savepoint = null; //保存点,记录操作的当前位置,之后可以回滚到指定的位置。(可以回滚一部分) try{ //1 获得连接 conn = ...; //2 开启事务 conn.setAutoCommit(false); A B savepoint = conn.setSavepoint(); C D //3 提交事务 conn.commit(); } catche(){ if(savepoint != null){ //CD异常 // 回滚到CD之前 conn.rollback(savepoint); // 提交AB conn.commit(); } else{ //AB异常 // 回滚AB conn.rollback(); } }
2.事务管理介绍
2.1三个顶级接口
PlatformTransactionManager :平台事务管理器,
spring要管理事务,必须使用事务管理器 进行事务配置时,必须配置事务管理器。
TransactionDefinition:事务详情(事务定义、事务属性),
spring用于确定事务具体详情,例如:隔离级别、是否只读、超时时间等进行事务配置时,必须配置详情。spring将配置项封装到该对象实例。
TransactionStatus:事务状态,
spring用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。spring底层根据状态进行相应操作。
2.2 PlatformTransactionManager 事务管理器
2.2.1 常见的事务管理器
DataSourceTransactionManager jdbc开发时事务管理器,采用JdbcTemplate
HibernateTransactionManager hibernate开发时事务管理器,整合hibernate
2.2.2 api详解
TransactionStatus getTransaction(TransactionDefinition definition) ,事务管理器 通过“事务详情”,获得“事务状态”,从而管理事务。
void commit(TransactionStatus status) 根据状态提交
void rollback(TransactionStatus status) 根据状态回滚
2.3 TransactionStatus 事务状态
2.4 TransactionDefinition 事务详情
2.4.1 隔离问题:
脏读:一个事务读到另一个事务没有提交的数据
不可重复读:一个事务读到另一个事务已提交的数据(update)
虚读(幻读):一个事务读到另一个事务已提交的数据(insert)
2.4.2 隔离级别:
read uncommitted:读未提交。存在3个问题
read committed:读已提交。解决脏读,存在2个问题
repeatable read:可重复读。解决:脏读、不可重复读,存在1个问题。
serializable :串行化。都解决,单事务。
2.4.3 传播行为
什么是事务的传播行为: 事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
PROPAGATION_REQUIRED , required , 必须 【默认值】
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将创建一个新的事务。
PROPAGATION_SUPPORTS ,supports ,支持
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将以非事务执行。
PROPAGATION_MANDATORY,mandatory ,强制
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将抛异常。
PROPAGATION_REQUIRES_NEW , requires_new ,必须新的
如果A有事务,将A的事务挂起,B创建一个新的事务
如果A没有事务,B创建一个新的事务
PROPAGATION_NOT_SUPPORTED ,not_supported ,不支持
如果A有事务,将A的事务挂起,B将以非事务执行
如果A没有事务,B将以非事务执行
PROPAGATION_NEVER ,never,从不
如果A有事务,B将抛异常
如果A没有事务,B将以非事务执行
PROPAGATION_NESTED ,nested ,嵌套
A和B底层采用保存点机制,形成嵌套事务。
掌握:PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED
3.案例实现事务管理
3.1搭建环境
3.1.1数据库:
3.1.2 Dao层接口及其实现类
@Repository public class UserDaoImpl implements UserDao{ @Resource//运用注解方式注入JdbcTemplate private JdbcTemplate jdbcTemplate; @Override public int addMoney(double money,Integer id) { int update = jdbcTemplate.update("update user set money=money+? where id=?", money, id); return update; } @Override public int removeMoney(double money,Integer id) { int update = jdbcTemplate.update("update user set money=money-? where id=?", money, id); return update; } }
3.1.3 service层接口及其实现类
@Service("userService") public class UserServiceImpl implements UserService { @Resource private UserDao userDao; @Override public void tranMoney(double money) { userDao.addMoney(money,1); //只能对运行时异常进行回滚 int i=1/0; userDao.removeMoney(money,2); } }
3.1.4 大配置文件数据源配置及事务管理器
<!--导入jdbc配置文件--> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <!-- 数据源配置--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!--包扫描仪--> <context:component-scan base-package="cn.spring.transaction"></context:component-scan> <!--设置JdbcTemplate模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!--事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
3.2采用代理工厂实现事务管理
<!--方式一:事务代理工厂--> <bean id="factoryBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!--设置事务管理器--> <property name="transactionManager" ref="transactionManager"></property> <!--设置目标对象--> <property name="target" ref="userService" ></property> <!--事务的隔离级别和传播行为--> <property name="transactionAttributes"> <props><!--键值 key为具体的方法名 value可以为传播行为或隔离级别--> <prop key="tranMoney">ISOLATION_READ_COMMITTED</prop> </props> </property> </bean>
3.3 Aop配置实现事务管理
<!--方式二:AOP实现事务--> <!--通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- transferMoney的事务隔离级别和传播行为 --> <tx:method name="tranMoney" propagation="REQUIRED" isolation="READ_COMMITTED"/> </tx:attributes> </tx:advice> <!--切面--> <aop:config> <aop:pointcut id="pointcut" expression="execution(* *..transaction.service.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor> </aop:config>
3.4基于注解实现事务管理
配置文件:
<!--使用注解实现事务--> <!--开启事务的注解配置--> <tx:annotation-driven/>
业务层注解:
@Service("userService") public class UserServiceImpl implements UserService { @Resource private UserDao userDao; @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED) @Override public void tranMoney(double money) { userDao.addMoney(money,1); //只能对运行时异常进行回滚 int i=1/0; userDao.removeMoney(money,2); } }