在使用多数据源时,如果不进行特殊处理,可能会出现事务不生效的问题。这是因为 Spring Boot 默认只会为一个数据源创建一个事务管理器,如果要使用多个数据源,就需要为每个数据源创建一个事务管理器,并在需要使用事务的方法或类上指定使用哪个事务管理器。
以下是解决事务不生效问题的具体步骤:
1. 在配置文件中配置多个数据源和相应的事务管理器,例如:
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/db1
username: root
password: root
secondary:
url: jdbc:mysql://localhost:3306/db2
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
# 配置事务管理器
spring.datasource.primary.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.primary.filters=stat,wall,log4j
spring.datasource.primary.maxActive=20
spring.datasource.primary.initialSize=1
spring.datasource.primary.maxWait=60000
spring.datasource.primary.minIdle=1
spring.datasource.primary.timeBetweenEvictionRunsMillis=60000
spring.datasource.primary.minEvictableIdleTimeMillis=300000
spring.datasource.primary.validationQuery=SELECT 1 FROM DUAL
spring.datasource.primary.testWhileIdle=true
spring.datasource.primary.testOnBorrow=false
spring.datasource.primary.testOnReturn=false
spring.datasource.primary.poolPreparedStatements=true
spring.datasource.primary.maxOpenPreparedStatements=20
spring.datasource.primary.filters=stat,wall,log4j
spring.datasource.primary.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.secondary.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.secondary.filters=stat,wall,log4j
spring.datasource.secondary.maxActive=20
spring.datasource.secondary.initialSize=1
spring.datasource.secondary.maxWait=60000
spring.datasource.secondary.minIdle=1
spring.datasource.secondary.timeBetweenEvictionRunsMillis=60000
spring.datasource.secondary.minEvictableIdleTimeMillis=300000
spring.datasource.secondary.validationQuery=SELECT 1 FROM DUAL
spring.datasource.secondary.testWhileIdle=true
spring.datasource.secondary.testOnBorrow=false
spring.datasource.secondary.testOnReturn=false
spring.datasource.secondary.poolPreparedStatements=true
spring.datasource.secondary.maxOpenPreparedStatements=20
spring.datasource.secondary.filters=stat,wall,log4j
spring.datasource.secondary.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 配置事务管理器
spring.datasource.primary.transaction-manager-name=primaryTransactionManager
spring.datasource.secondary.transaction-manager-name=secondaryTransactionManager
2. 创建多个事务管理器的 Bean,例如
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
return new DataSourceTransactionManager(primaryDataSource);
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
return new DataSourceTransactionManager(secondaryDataSource);
}
}
3. 在需要使用事务的方法或类上使用 @Transactional 注解,并指定使用哪个事务管理器,例如:
@Service
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("primaryTransactionManager")
private PlatformTransactionManager primaryTransactionManager;
@Autowired
@Qualifier("secondaryTransactionManager")
private PlatformTransactionManager secondaryTransactionManager;
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
@Override
@Transactional(transactionManager = "primaryTransactionManager")
public void addUserToPrimary(User user) {
// 使用 primaryDataSource 数据源进行操作
}
@Override
@Transactional(transactionManager = "secondaryTransactionManager")
public void addUserToSecondary(User user) {
// 使用 secondaryDataSource 数据源进行操作
}
}