一、事务管理方案
声明式事务底层采用AOP技术,在service层手动添加事务就可以解决上一篇提到的问题。
1. 修改业务层代码
代码语言:javascript复制添加一个SqlSessionTemplate对象,让我们对业务方法进行try catch,没有异常则进行提交,捕捉到异常回滚即可。
package com.example.service;
import com.example.dao.AccountDao;
import com.example.pojo.Account;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private SqlSessionTemplate sessionTemplate;
/**
*
* @param id1 转出人id
* @param id2 转入人id
* @param price 金额
*/
// 作用方法上时,该方法都将具有该类型事务的事务属性
public void transfer(int id1,int id2, double price){
try {
// 转出人减少余额
Account account1 = accountDao.findById(id1);
account1.setBalance(account1.getBalance() - price);
accountDao.update(account1);
// 模拟程序出错
int i = 1 / 0;
// 转入人增加余额
Account account2 = accountDao.findById(id2);
account2.setBalance(account2.getBalance() price);
accountDao.update(account2);
sessionTemplate.commit();
}
catch (Exception e){
e.printStackTrace();
sessionTemplate.rollback();
}
}
}
2. 测试
OK,可以看到这里程序是出现异常中断了的。 现在观看数据库里面的情况是怎么样的。
点击这里查看运行结果
OK,可以看到这里张三确实没有被扣钱啊,所以手动提交事务也是可以的,但是这样我们的try catch就太多了。因此有了事务管理器。
二、事务管理器
1. 简介
Spring依赖事务管理器进行事务管理,事务管理器即一个通知类,我们为该通知类设置切点为service层方法即可完成事务自动管理。由于不同技术操作数据库,进行事务操作的方法不同。如:JDBC提交事务是 connection.commit() ,MyBatis提交事务是 sqlSession.commit() ,所以Spring提供了多个事务管理器。
事务管理器名称 | 作用 |
---|---|
org.springframework.jdbc.datasource.DataSourceTransactionManager | 针对JDBC技术提供的事务管理器。适用于JDBC和MyBatis。 |
org.springframework.orm.hibernate3.HibernateTransactionManager | 针对于Hibernate框架提供的事务管理器。适用于Hibernate框架。 |
org.springframework.orm.jpa.JpaTransactionManager | 针对于JPA技术提供的事务管理器。适用于JPA技术。 |
org.springframework.transaction.jta.JtaTransactionManager | 跨越了多个事务管理源。适用在两个或者是多个不同的数据源中实现事务控制。 |
我们使用MyBatis操作数据库,接下来使用 DataSourceTransactionManager 进行事务管理。
2. 在配置文件中引入约束
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
3. 进行事务配置
在applicationContext.xml文件新增配置
代码语言:javascript复制 <!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 进行事务相关配置 -->
<tx:advice id = "txAdvice">
<tx:attributes>
<!-- 代表所有方法 -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut id="pointcut" expression="execution(* com.example.service..*(..))"/>
<!-- 配置通知 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
三、事务控制的API
事务管理器都实现了PlatformTransactionManager接口,Spring进行事务控制的功能是由三个接口提供的,这三个接口是Spring实现的,在开发中我们很少使用到,只需要了解他们的作用即可:
1. PlatformTransactionManager接口
PlatformTransactionManager是Spring提供的事务管理器接口,所有事务管理器都实现了该接口。该接口中提供了三个事务操作方法:
- TransactionStatus getTransaction(TransactionDefinition definition):获取事务状态信息。
- void commit(TransactionStatus status):事务提交
- void rollback(TransactionStatus status):事务回滚
2. TransactionDefinition接口
TransactionDefinition是事务的定义信息对象,它有如下方法:
- String getName():获取事务对象名称。
- int getIsolationLevel():获取事务的隔离级别。
- int getPropagationBehavior():获取事务的传播行为。
- int getTimeout():获取事务的超时时间。
- boolean isReadOnly():获取事务是否只读。
3. TransactionStatus接口
TransactionStatus是事务的状态接口,它描述了某一时间点上事务的状态信息。它有如下方法:
- void flush() 刷新事务
- boolean hasSavepoint() 获取是否存在保存点
- boolean isCompleted() 获取事务是否完成
- boolean isNewTransaction() 获取是否是新事务
- boolean isRollbackOnly() 获取是否回滚
- void setRollbackOnly() 设置事务回滚
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!