什么是事务:
数据库事务是指作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么全部不执行,事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。一个逻辑工作单元要成为事务,必须满足所谓的 ACID(原子性、一致性、隔离性和持久性)属性,事务是数据库运行中的逻辑工作单位,由数据库中的事务管理子系统负责事务的处理。
springBoot事务管理机制
-
spring事务管理分为两种方式:
- 编程式事务,指的是通过编码方式实现事务;
- 声明式事务,基于AOP,将具体业务逻辑与事务处理解耦。
声明式事务是什么
声明式事务是建立在 AOP 机制之上的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
声明式事务最大的优点,就是通过 AOP 机制将具体业务逻辑与事务处理解耦,不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,因此在实际使用中声明式事务用的比较多。
声明式事务有两种方式:一种是在 XML 配置文件中做相关的事务规则声明;另一种是基于 @Transactional
注解的方式(@Transactional
注解是来自 org.springframework.transaction.annotation
包),便可以将事务规则应用到业务逻辑中。
未使用springboot事务管理机制的配置如下
<!-- 事务管理 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务通知属性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 定义事务传播属性 -->
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="import*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="upd*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="set*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切面 -->
<aop:config>
<aop:pointcut id="serviceOperation"
expression="(execution(* com.ssm.demo.service.*.*(..)))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
</aop:config>
通过这段代码我们也能够看出声明式事务的配置过程:
- 配置事务管理器
- 配置事务通知属性
- 配置事务切面
这样配置后,相关方法在执行时都被纳入事务管理下了,一旦发生异常,事务会正确回滚。
那么在 SpringBoot 中,建议采用注解 @Transactional
进行事务的控制,只需要在需要进行事务管理的方法或者类上添加 @Transactional
注解即可,下面我们来看看这个简单的方法
一般事务处理都是在service层进行,实例代码如下:
@Service
public class TransactionTestService {
@Resource
UserDao userDao;
//这是没有添加事务管理机制的代码
public Boolean demo1() {
User user = new User();
user.setPassword("password1");
user.setName("demo1");
// 在数据库表中新增一条记录
userDao.insertUser(user);
// 发生异常
System.out.println(1 / 0);
return true;
}
@Transactional
public Boolean tdemo2() {
User user = new User();
user.setPassword("password2");
user.setName("demo2");
// 在数据库表中新增一条记录
userDao.insertUser(user);
// 发生异常
System.out.println(1 / 0);
return true;
}
}
总结
在应用系统调用声明了 @Transactional
的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据 @Transactional
的属性配置信息,这个代理对象决定该声明 @Transactional
的目标方法是否由拦截器 TransactionInterceptor 来使用拦截,在 TransactionInterceptor 拦截时,会在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑, 最后根据执行情况是否出现异常,利用抽象事务管理器 AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务