1. SSM使用事务

1.1 导入JDBC依赖包

众所周知,凡是需要跟数据库打交道的,基本上都要添加jdbc的依赖,在Spring项目中,加入的是spring-jdbc依赖:

1
2
3
4
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>

1.2 配置版事务

在使用配置文件的方式中,通常会在Spring的配置文件中配置事务管理器,并注入数据源:

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 注册数据源 -->
<bean id="dataSource" class="...">
<property name="" value=""/>
</bean>

<!-- 注册事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="txManager" />

接下来可以直接在业务层Service的方法上或者类上添加**@Transactional**。

1.3 注解版事务

首先需要注册两个Bean,分别对应上面Spring配置文件中的两个Bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@EnableTransactionManagement//重要
@Configuration
public class TxConfig {

@Bean
public DataSource dataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("...");
dataSource.setPassword("...");
dataSource.setDriverClass("...");
dataSource.setJdbcUrl("...");
return dataSource;
}

//重要
@Bean
public PlatformTransactionManager platformTransactionManager() {
return new DataSourceTransactionManager(dataSource());//放入数据源
}
}

我们看到往Spring容器中注入了DataSource 和PlatformTransactionManager 对象,并且通过@EnableTransactionManagement注解开启了事务,和上面的XML配置是一一对应的。PlatformTransactionManager这个Bean非常重要,要使用事务管理,就必须要在IOC容器中注册一个事务管理器。

1
2
3
4
5
6
7
8
public interface PlatformTransactionManager {
//获取一个Transaction
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
//提交事务
void commit(TransactionStatus var1) throws TransactionException;
//回滚事务
void rollback(TransactionStatus var1) throws TransactionException;
}

我们看到事务管理器的作用就是获取事务,提交回滚事务。

2. SpringBoot自动配置事务

2.1 引入JDBC

众所周知,在SpringBoot中凡是需要跟数据库打交道的,基本上都要显式或者隐式添加jdbc的依赖:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

也就是jdbc的场景启动器,我们点进去看看。

img

其实也是引入了spring-jdbc的依赖,接下来我们要看两个重要的事务自动配置类

3. DataSourceTransactionManagerAutoConfiguration

img

我们看到在spring.factories中配置了事务管理器自动配置类DataSourceTransactionManagerAutoConfiguration,我们进去看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Configuration
//在类路径下有这个类存在PlatformTransactionManager时,这个配置类才会生效
//而前面我们已经引入了spring-boot-starter-jdbc,那自然是存在了
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration {

@Configuration
@ConditionalOnSingleCandidate(DataSource.class)
static class DataSourceTransactionManagerConfiguration {

private final DataSource dataSource;

private final TransactionManagerCustomizers transactionManagerCustomizers;

DataSourceTransactionManagerConfiguration(DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
this.dataSource = dataSource;
this.transactionManagerCustomizers = transactionManagerCustomizers
.getIfAvailable();
}

@Bean
//没有当Spring容器中不存在PlatformTransactionManager这个对象时,创建DataSourceTransactionManager
//也就是如果我们自定义了DataSourceTransactionManager并注入Spring容器,这里将不会执行
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public DataSourceTransactionManager transactionManager(DataSourceProperties properties) {
//创建DataSourceTransactionManager注入Spring容器,并且把dataSource传进去
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
}

}

}

很明显只要我们导入了spring-boot-starter-jdbc场景启动器,并且我们没有自定义DataSourceTransactionManager,那么事务管理器自动配置类DataSourceTransactionManagerAutoConfiguration会自动为我们创建DataSourceTransactionManager并注入Spring容器中。但是这还不够,我们前面还是需要通过**@EnableTransactionManagement开启事务呢**,如果不开启事务,@Transactional是不起任何作用的。下面我们就来看看是如何开启事务的

4. TransactionAutoConfiguration

img

我们看到在spring.factories中配置了事务自动开启配置类TransactionAutoConfiguration,我们进去看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@Configuration
//和DataSourceTransactionManagerAutoConfiguration中是一样的
//引入了spring-boot-starter-jdbc,那自然是存在了PlatformTransactionManager
@ConditionalOnClass({PlatformTransactionManager.class})
//这个自动配置类必须要在DataSourceTransactionManagerAutoConfiguration这个自动配置类之后才能生效
//也就是前面我们已经往Spring容器中注入了DataSourceTransactionManager这个对象才执行这个配置类
@AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
@EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
public TransactionAutoConfiguration() {
}

@Configuration
@ConditionalOnBean({PlatformTransactionManager.class})
@ConditionalOnMissingBean({AbstractTransactionManagementConfiguration.class})
public static class EnableTransactionManagementConfiguration {
public EnableTransactionManagementConfiguration() {
}

@Configuration
//重点:通过 @EnableTransactionManagement注解开启事务
//可以看到和我们自己使用@EnableTransactionManagement是一样的
@EnableTransactionManagement(
proxyTargetClass = true
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "true",
matchIfMissing = true
)
public static class CglibAutoProxyConfiguration {
public CglibAutoProxyConfiguration() {
}
}

@Configuration
@EnableTransactionManagement(
proxyTargetClass = false
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "false",
matchIfMissing = false
)
public static class JdkDynamicAutoProxyConfiguration {
public JdkDynamicAutoProxyConfiguration() {
}
}
}

@Configuration
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
public static class TransactionTemplateConfiguration {
private final PlatformTransactionManager transactionManager;

public TransactionTemplateConfiguration(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}

@Bean
@ConditionalOnMissingBean
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(this.transactionManager);
}
}
}

我们看到TransactionAutoConfiguration这个自动配置类必须要在DataSourceTransactionManagerAutoConfiguration这个配置类之后才能生效,也就是前面我们已经往Spring容器中注入了DataSourceTransactionManager这个对象才执行这个配置类,然后通过

@EnableTransactionManagement这个注解开启事务,其实和我们自己使用@EnableTransactionManagement是一样的

因此,只要我们在SpringBoot中引入了spring-boot-starter-jdbc这个场景启动器,就会帮我们自动开启事务了,我们只需要使用@Transactional就可以了

5. mybatis-spring-boot-starter

大多数时候我们在SpringBoot中会引入Mybatis这个orm框架,Mybaits的场景启动器如下

1
2
3
4
5
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>

我们点进去看看

img

我们看到mybatis-spring-boot-starter这个场景启动器是引入了spring-boot-starter-jdbc这个场景启动器的,因此只要我们在SpringBoot中使用Mybaits,是自动帮我们开启了Spring事务的

6. 总结

springboot 开启事物很简单,只需要加一行注解**@Transactional**就可以了,前提你用的是jdbctemplate, jpa, Mybatis,这种常见的orm。


本站由 卡卡龙 使用 Stellar 1.29.1主题创建

本站访问量 次. 本文阅读量 次.