这一篇来重点讲讲Spring中的事务。
1、Spring和事务的关系:
- 事务性资源:如关系型数据库Mysql、Oracle、某些消息队列中间件等,因为它们本身支持事务,也能够处理事务。
- Spring不是事务性资源,但是它可以管理事务性资源,所以Spring和事务之间是管理关系。
2、Spring事务三要素:
- 数据源:表示具体的事务性资源,是事务的真正处理者,如MySQL等。
- 事务管理器:像一个大管家,从整体上管理事务的处理过程,如打开、提交、回滚等。
- 事务应用和属性配置:像一个标识符,表明哪些方法要参与事务,如何参与事务,以及一些相关属性如隔离级别、超时时间等。
3、事务的基本原理:
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:
- 获取连接
Connection con = DriverManager.getConnection()
- 开启事务
con.setAutoCommit(true/false);
- 执行CRUD
- 提交事务/回滚事务
con.commit() / con.rollback();
- 关闭连接
conn.close();
使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。
以注解方式为例子:
1、配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
2、spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。
3、真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
4.事务类型
分为两种:编程式事务、声明式事务
(1)编程式事务
编程式事务管理使用TransactionTemplate
或者直接使用底层的PlatformTransactionManager
。对于编程式事务管理,spring推荐使用TransactionTemplate
。很少用,但是可以看下官网的例子:
public class SimpleService implements Service {
private final TransactionTemplate transactionTemplate;
// 使用构造对transactionTemplate进行初始化
// 需要提供一个transactionManager
public SimpleService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
public Object someServiceMethod() {
return transactionTemplate.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
// 这里实现自己的相关业务逻辑
updateOperation1();
return resultOfUpdateOperation2();
}
});
}
}
在上面的例子中,显示的使用了 TransactionTemplate 来完成事务管理,通过实现 TransactionCallback 接口并在其 doInTransaction 方法中完成了我们对业务的处理。我们可以大概看下 TransactionTemplate的execute 方法的实现,实际上就是通过一个 TransactionCallback 封装了业务逻辑,然后 TransactionTemplate 会在事务的上下文中调用:
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
// 1.通过事务管理器开启事务
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
// 2.执行传入的业务逻辑
result = action.doInTransaction(status);
}
catch (RuntimeException | Error ex) {
// 3.出现异常,进行回滚
rollbackOnException(status, ex);
throw ex;
}
catch (Throwable ex) {
// 3.出现异常,进行回滚
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex,
"TransactionCallback threw undeclared checked exception");
}
// 4.正常执行完成的话,提交事务
this.transactionManager.commit(status);
return result;
}
}
(2)声明式事务
声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理也有两种常用的方式,一种是基于xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。
Spring事务配置
spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。
网友评论