大白话讲解Spring对数据源和事务管理以及多数据源配置
在我们的开发过程中,Springboot项目里面我们会在配置文件里面配置数据库的账号密码以及连接地址,
spring.datasource.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
其实这些就已经够了,已经足够让我们的项目启动连接上数据库了,但是往往我们还会配置数据库连接池,
spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
Spring就会将这些配置封装到对应的数据源DataSource上,然后事务管理器会以此数据源作为Spring事务管理器里面的数据源,然后此事务管理器操作的所有事务都会对应到该数据源对应的数据库上,JDBCTemplate默认也会绑定到改默认的数据源上,通过jdbcTemplate操作的SQL语句,也都是该数据库中的表和数据。如果框架里面ORM用的是Mybaits也行,也就是下图中的mapper。
Spring+多数据源+数据库连接池+事务管理器+事务+JDBCTemplate(Demo)
在基于JdbcTemplate
的多数据源配置中,加入数据库连接池(如HikariCP
)能够提升性能和资源管理效率。Spring Boot默认使用HikariCP
作为连接池,我们可以直接在配置文件中指定连接池属性。以下是完整的配置步骤,包括DataSource
、JdbcTemplate
、事务管理器和连接池的配置:
1. 添加依赖
确保项目中已经引入了Spring JDBC和MySQL驱动的依赖。HikariCP
作为Spring Boot默认连接池,会被自动引入:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
2. 配置数据源和连接池属性
在application.yml
或application.properties
中配置主数据源和次数据源的连接池属性。这里以application.yml
为例:
spring:datasource:primary:url: jdbc:mysql://localhost:3306/primary_dbusername: primary_userpassword: primary_passdriver-class-name: com.mysql.cj.jdbc.Driverhikari:maximum-pool-size: 10 # 最大连接数minimum-idle: 5 # 最小空闲连接数idle-timeout: 30000 # 空闲连接超时时间max-lifetime: 1800000 # 连接最大存活时间connection-timeout: 20000 # 连接超时时间secondary:url: jdbc:mysql://localhost:3306/secondary_dbusername: secondary_userpassword: secondary_passdriver-class-name: com.mysql.cj.jdbc.Driverhikari:maximum-pool-size: 8minimum-idle: 4idle-timeout: 30000max-lifetime: 1800000connection-timeout: 20000
3. 配置多个DataSource
和JdbcTemplate
为每个数据源创建独立的DataSource
Bean和JdbcTemplate
实例,确保DataSource
采用HikariDataSource
连接池:
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;@Configuration
public class DataSourceConfig {// 配置主数据源并启用HikariCP@Bean(name = "primaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().type(com.zaxxer.hikari.HikariDataSource.class).build();}// 配置次数据源并启用HikariCP@Bean(name = "secondaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().type(com.zaxxer.hikari.HikariDataSource.class).build();}// 主数据源的JdbcTemplate@Bean(name = "primaryJdbcTemplate")public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource) {return new JdbcTemplate(dataSource);}// 次数据源的JdbcTemplate@Bean(name = "secondaryJdbcTemplate")public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {return new JdbcTemplate(dataSource);}// 主数据源的事务管理器@Bean(name = "primaryTransactionManager")public PlatformTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}// 次数据源的事务管理器@Bean(name = "secondaryTransactionManager")public PlatformTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
4. 使用JdbcTemplate
和指定事务管理器
在服务类中,通过@Qualifier
注解选择正确的JdbcTemplate
和事务管理器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class SomeService {private final JdbcTemplate primaryJdbcTemplate;private final JdbcTemplate secondaryJdbcTemplate;@Autowiredpublic SomeService(@Qualifier("primaryJdbcTemplate") JdbcTemplate primaryJdbcTemplate,@Qualifier("secondaryJdbcTemplate") JdbcTemplate secondaryJdbcTemplate) {this.primaryJdbcTemplate = primaryJdbcTemplate;this.secondaryJdbcTemplate = secondaryJdbcTemplate;}@Transactional("primaryTransactionManager")public void operateOnPrimaryDataSource() {primaryJdbcTemplate.update("INSERT INTO example_table (column1) VALUES (?)", "value1");}@Transactional("secondaryTransactionManager")public void operateOnSecondaryDataSource() {secondaryJdbcTemplate.update("INSERT INTO example_table (column1) VALUES (?)", "value2");}
}
5. 配置完成后的注意事项
- 优化连接池:调整连接池参数(如
maximum-pool-size
、connection-timeout
)以适应应用负载需求。 - 观察连接池状态:启动应用后检查日志,确保连接池和各个数据源、事务管理器正确初始化。
- 事务传播设置:在不同数据源之间切换时,可以根据业务需求调整事务传播(如
REQUIRES_NEW
),确保数据一致性。
这样,通过配置多数据源、连接池和事务管理器,就可以利用JdbcTemplate
实现多数据源操作。连接池管理有助于提升应用的资源利用效率和并发性能。
Spring+多数据源+数据库连接池+事务管理器+事务+Mybatis(Demo)
在使用MyBatis替换JdbcTemplate
进行多数据源配置时,需要配置多个数据源和会话工厂(SqlSessionFactory
)以及对应的事务管理器。MyBatis的多数据源配置可以通过为每个数据源创建独立的SqlSessionFactory
和DataSourceTransactionManager
来实现。
以下是基于Spring Boot和MyBatis的多数据源配置步骤:
1. 添加依赖
确保引入了MyBatis的依赖和MySQL驱动:
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.0</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
2. 配置数据源和连接池属性
在application.yml
或application.properties
中配置主数据源和次数据源的连接池属性:
spring:datasource:primary:url: jdbc:mysql://localhost:3306/primary_dbusername: primary_userpassword: primary_passdriver-class-name: com.mysql.cj.jdbc.Driverhikari:maximum-pool-size: 10minimum-idle: 5idle-timeout: 30000max-lifetime: 1800000connection-timeout: 20000secondary:url: jdbc:mysql://localhost:3306/secondary_dbusername: secondary_userpassword: secondary_passdriver-class-name: com.mysql.cj.jdbc.Driverhikari:maximum-pool-size: 8minimum-idle: 4idle-timeout: 30000max-lifetime: 1800000connection-timeout: 20000
3. 配置DataSource
、SqlSessionFactory
和事务管理器
SqlSessionFactoryBean 是 MyBatis 提供的一个工厂类,用于创建 SqlSessionFactory 对象。SqlSessionFactory 是 MyBatis 中的核心对象,它负责创建 SqlSession 实例,通过这些实例可以执行数据库操作。
在 Spring 环境中,SqlSessionFactoryBean 可以简化 SqlSessionFactory 的配置和创建过程。通常我们在配置文件中定义 SqlSessionFactoryBean Bean,并且绑定数据源、配置文件、映射文件等信息。SqlSessionFactoryBean 会根据这些配置生成一个 SqlSessionFactory 实例。
SqlSessionFactoryBean 的主要功能和作用,绑定数据源:将 DataSource 注入 SqlSessionFactoryBean,从而让 SqlSessionFactory 使用该数据源进行数据库连接管理。配置 MyBatis 属性:可以通过 SqlSessionFactoryBean 设置 MyBatis 的全局配置属性,例如开启缓存、日志输出级别等。加载 MyBatis 配置文件:支持加载 MyBatis 主配置文件(mybatis-config.xml),其中可以设置 MyBatis 的详细配置。注册别名和插件:可以通过配置别名或插件,让 MyBatis 使用简化的类名(如 @Alias),并增强功能(如 PageHelper 分页插件)。
为每个数据源创建独立的DataSource
Bean、SqlSessionFactory
和事务管理器:
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;@Configuration
public class DataSourceConfig {// 主数据源配置@Primary@Bean(name = "primaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}// 次数据源配置@Bean(name = "secondaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}// 主数据源的SqlSessionFactory@Primary@Bean(name = "primarySqlSessionFactory")public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);return sessionFactory.getObject();}// 次数据源的SqlSessionFactory@Bean(name = "secondarySqlSessionFactory")public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);return sessionFactory.getObject();}// 主数据源的事务管理器@Primary@Bean(name = "primaryTransactionManager")public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}// 次数据源的事务管理器@Bean(name = "secondaryTransactionManager")public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
4. 配置MapperScan
扫描不同数据源的Mapper
使用@MapperScan
注解指定每个数据源的SqlSessionFactory
,分别扫描不同的Mapper包路径:
// 主数据源的Mapper扫描配置
@Configuration
@MapperScan(basePackages = "com.example.primary.mapper", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryMyBatisConfig {
}// 次数据源的Mapper扫描配置
@Configuration
@MapperScan(basePackages = "com.example.secondary.mapper", sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryMyBatisConfig {
}
5. 在Service中使用不同的数据源和事务管理器
在Service层中,通过@Transactional
注解指定不同的事务管理器,以便切换数据源:
import com.example.primary.mapper.PrimaryMapper;
import com.example.secondary.mapper.SecondaryMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class SomeService {private final PrimaryMapper primaryMapper;private final SecondaryMapper secondaryMapper;@Autowiredpublic SomeService(PrimaryMapper primaryMapper, SecondaryMapper secondaryMapper) {this.primaryMapper = primaryMapper;this.secondaryMapper = secondaryMapper;}@Transactional("primaryTransactionManager")public void operateOnPrimaryDataSource() {primaryMapper.insertData("primary data");}@Transactional("secondaryTransactionManager")public void operateOnSecondaryDataSource() {secondaryMapper.insertData("secondary data");}
}
6. 配置完成后的注意事项
- 优化连接池配置:根据应用负载调整Hikari连接池参数。
- 事务管理:确保在
@Transactional
中使用正确的事务管理器来区分数据源。 - 数据源切换检查:启动应用时查看日志,确认每个
DataSource
、SqlSessionFactory
和事务管理器是否正确初始化。
这样,就可以通过配置MyBatis、数据源、事务管理器和Mapper扫描路径来实现MyBatis的多数据源管理。