Spring事务管理
- 在工作中遇到了spring事务失效的情况,所以记录一下原因,也希望能帮助大家解决困惑,如果有不对的地方欢迎大家指正。
事务
- 概念:事务(Transaction)是计算机科学中的一个术语,用于描述一组操作,这些操作要么全部成功执行,要么全部不执行,以确保数据的完整性和一致性。
- 事务的主要特性(ACID属性)
特性 | 具体定义 |
---|---|
原子性 | 事务中的所有操作要么全部完成,要么全部不完成。如果事务中的某个操作失败,整个事务将被回滚到事务开始前的状态。 |
一致性 | 事务执行前后,系统必须处于一致的状态。 |
隔离性 | 一个事务的执行不能被其他事务干扰。并发执行的事务之间,彼此的操作应该是相互独立的。 |
持久性 | 一旦事务提交,它对系统的影响是永久性的。即使系统发生故障,已提交的事务的结果也不会丢失。 |
- 事务的类型:
类型 | 具体定义 |
---|---|
数据库事务 | 数据库操作中,事务用于确保数据的完整性和一致性。比如银行转账 |
分布式事务 | 在分布式系统中,事务涉及多个网络节点,需要确保所有节点上的操作要么全部成功,要么全部失败。 |
消息事务 | 在消息队列系统中,事务确保消息的发送和接收是原子性的,例如,确保消息在发送到队列之前不会被部分处理。 |
网络事务 | 在网络通信中,事务可以确保数据包的完整传输,如果传输过程中断,事务可以确保数据包不会部分到达。 |
SpringBoot事务的使用
- 开启@EnableTransactionManagement(springboot 2.x 可以省略)
- 使用@Transcational
事务管理器
PlatformTransactionManager接口
- PlatformTransactionManager是 Spring 框架中定义的一个接口,它是 Spring 事务管理的核心组件之一。它是一个用于管理事务的高级接口,提供了一种透明的方式来管理事务,无论底层使用的是什么类型的数据存储。
- 在 Spring 中,事务管理可以通过编程方式(使用 TransactionTemplate)或声明式方式(使用 @Transactional 注解)来实现。
- PlatformTransactionManager 定义了一组方法,允许 Spring 框架以统一的方式执行事务管理,而与底层的事务实现(如 JDBC、JTA、JPA、Hibernate 等)无关。
PlatformTransactionManager接口的关键方法(简单列举几个)
方法名 | 功能 |
---|---|
TransactionStatus getTransaction(@Nullable TransactionDefinition definition, @Nullable Object hints) | 开始一个新的事务,并返回代表新事务状态的TransactionStatus对象。 |
void commit(TransactionStatus status) | 提交事务。 |
void rollback(TransactionStatus status) | 回滚事务。 |
PlatformTransactionManager接口的实现类(简单列举几个)
类名 | |
---|---|
DataSourceTransactionManager | 用于管理JDBC和一些ORM工具(如Hibernate)的事务。它直接依赖于数据源(DataSource)来执行事务管理。 |
JpaTransactionManager | 用于JPA事务管理。 |
HibernateTransactionManager | 专门用于Hibernate事务管理。 |
- 你可以在启动类中添加如下方法,Debug测试,就能知道自动注入的是 PlatformTransactionManager 接口的哪个实现类。
@EnableTransactionManagement // 启注解事务管理,等同于xml配置方式的 <tx:annotation-driven />
@SpringBootApplication
public class DemoApplication {
@Bean
public Object testBean(PlatformTransactionManager platformTransactionManager){
System.out.println(">>>>>>>>>>" + platformTransactionManager.getClass().getName());
return new Object();
}
public static void main(String[] args) {
SpringApplication.run(ProfiledemoApplication.class, args);
}
}
Springboot自动配置事务管理器
-
TransactionAutoConfiguration在spring-boot-auticonfigure.jar中
-
DataSourceTransactionManagerAutoConfiguration在spring-boot-auticonfigure.jar中
-
当你导入了spring-jdbc相关的jar,就会默认帮你引入jdbcTemplate.class和DataSourceTransactionManager.class( extends AbstractPlatformTransactionManager implements PlatformTransactionManager extends TransactionManager)
-
另外需要注意一点,就是DataSourceTransactionManagerAutoConfiguration中@ConditionalOnSingleCandidate(DataSource.class)这个注解,也就是当你只有一个数据源的时候springboot会默认帮你配置DataSourceTransactionManager。但是当你有多个数据源的时候springboot就不会帮你默认配置了,你需要自己配置!
@AutoConfiguration(before = TransactionAutoConfiguration.class)
@ConditionalOnClass({ JdbcTemplate.class, TransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(DataSource.class)
static class JdbcTransactionManagerConfiguration {
@Bean
@ConditionalOnMissingBean(TransactionManager.class)
DataSourceTransactionManager transactionManager(Environment environment, DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
DataSourceTransactionManager transactionManager = createTransactionManager(environment, dataSource);
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
return transactionManager;
}
private DataSourceTransactionManager createTransactionManager(Environment environment, DataSource dataSource) {
return environment.getProperty("spring.dao.exceptiontranslation.enabled", Boolean.class, Boolean.TRUE)
? new JdbcTransactionManager(dataSource) : new DataSourceTransactionManager(dataSource);
}
}
}
spring的DataSourceTransactionManager不支持管理多个数据源的事务
-
DataSourceTransactionManager 是 Spring 框架中的一个事务管理器,它是基于 JDBC 的本地事务管理。它支持通过 JDBC 的 Connection 对象来管理事务,包括开启事务、提交事务和回滚事务。然而,DataSourceTransactionManager 并不支持直接管理多个数据源的事务,原因如下:
-
本地事务模型:
DataSourceTransactionManager 基于 JDBC 的本地事务模型,它依赖于单个数据源提供的 Connection 对象来管理事务。在 JDBC 中,事务是与单个数据库连接绑定的,这意味着事务的边界是由单个数据源控制的。 -
单一数据源:
DataSourceTransactionManager 设计时就假定了单个数据源的场景。它管理事务的方式是针对单个数据源的连接进行的,没有考虑到跨数据源的事务管理。 -
全局事务的复杂性:
跨多个数据源的事务通常需要全局事务管理器来协调,这通常涉及到分布式事务。全局事务的管理和协调比单个数据源的事务要复杂得多,需要考虑网络延迟、事务的一致性、隔离级别、锁策略等因素。 -
分布式事务的解决方案:
对于需要跨多个数据源管理事务的场景,通常使用分布式事务的解决方案,如 Java Transaction API (JTA)、两阶段提交 (2PC) 或者是像 Spring Cloud 的分布式事务解决方案。这些解决方案可以协调多个数据源或服务的事务。
-
-
Spring 的设计哲学:Spring 框架的设计哲学是“为复杂控制提供简单的抽象”,但在多数据源事务管理方面,这种简单的抽象不足以满足复杂的需求。因此,Spring 没有在 DataSourceTransactionManager 中内置这种复杂的功能。
-
如果你需要管理跨多个数据源的事务,你可以考虑以下解决方案:
- JTA(Java Transaction API):使用 JtaTransactionManager 或类似的事务管理器来管理全局事务。
- 分布式事务框架:使用如 Atomikos、Narayana 等分布式事务管理器。
- 数据库支持:使用支持分布式事务的数据库特性,如 MySQL 的 XA 或 Oracle 的全局事务。
- 框架支持:使用 Spring Cloud 的分布式事务解决方案,如 Spring Cloud Sleuth 和 Spring Cloud Circuit Breaker。
- 在设计系统时,如果预计会需要跨多个数据源的事务管理,应该从一开始就考虑使用适合的分布式事务解决方案。
如果还有兴趣了解spring事务失效的情况,可以看这一篇:简单回顾Spring事务失效的情况