1、背景
在实际项目开发过程中,时不时会遇到多数据源的情况。本文介绍 Spring Boot 集成 MyBatis 实现多数据源支持的基本方式。
2、集成过程
工程结构
示例工程结构如下。org.spring.springboot.config.datasource 包含多数据源配置;如果需要第三个数据源,可以按已有配置扩展。resources/mapper 目录下有两个模块,分别对应 MyBatis 不同数据源需要扫描的 mapper.xml 目录。
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
| ├── pom.xml └── src └── main ├── java │ └── com │ └── clang │ ├── Application.java │ ├── config │ │ └── datasource │ │ ├── ClusterDataSourceConfig.java │ │ └── MasterDataSourceConfig.java │ ├── controller │ │ └── UserRestController.java │ ├── dao │ │ ├── cluster │ │ │ └── CityDao.java │ │ └── master │ │ └── UserDao.java │ ├── domain │ │ ├── City.java │ │ └── User.java │ └── service │ ├── UserService.java │ └── impl │ └── UserServiceImpl.java └── resources ├── application.properties └── mapper ├── cluster │ └── CityMapper.xml └── master └── UserMapper.xml
|
pom.xml
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
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.clang</groupId> <artifactId>springboot-mybatis-mutil-datasource</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>springboot-mybatis-mutil-datasource</name> <description>Demo project for Spring Boot</description>
<!-- springboot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.8.RELEASE</version> </parent> <!-- springboot -->
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <mybatis-spring-boot>2.1.4</mybatis-spring-boot> <mysql-connector>8.0.11</mysql-connector> <druid>1.1.24</druid> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<!-- Spring Boot MyBatis 依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis-spring-boot}</version> </dependency>
<!-- MySQL 连接驱动依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector}</version> </dependency>
<!-- Druid 数据连接池依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid}</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
配置数据源
1 2 3 4 5 6 7 8 9 10 11
| ## master 数据源配置 master.datasource.url=jdbc:mysql: master.datasource.username=root master.datasource.password=root master.datasource.driverClassName=com.mysql.cj.jdbc.Driver
## cluster 数据源配置 cluster.datasource.url=jdbc:mysql: cluster.datasource.username=root cluster.datasource.password=root cluster.datasource.driverClassName=com.mysql.cj.jdbc.Driver
|
多数据源配置类
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
| @Configuration
@MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory") public class MasterDataSourceConfig {
static final String PACKAGE = "com.clang.dao.master"; static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml";
@Value("${master.datasource.url}") private String url;
@Value("${master.datasource.username}") private String user;
@Value("${master.datasource.password}") private String password;
@Value("${master.datasource.driverClassName}") private String driverClass;
@Bean(name = "masterDataSource") @Primary public DataSource masterDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driverClass); dataSource.setUrl(url); dataSource.setUsername(user); dataSource.setPassword(password); return dataSource; }
@Bean @Primary public DataSourceTransactionManager masterTransactionManager() { return new DataSourceTransactionManager(masterDataSource()); }
@Bean(name = "masterSqlSessionFactory") @Primary public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(masterDataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(MasterDataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject(); } }
|
@Primary 表示当存在多个同类 Bean 候选时,优先使用该 Bean。多数据源配置中通常需要明确一个主数据源,并使用 @Primary 标记。
@MapperScan 用于扫描 Mapper 接口并交给容器管理。这里将包路径精确到 master,是为了和下面的 cluster 数据源区分开。@Value 从全局配置文件 application.properties 中读取配置,sqlSessionFactoryRef 指定当前 Mapper 绑定到哪个 SqlSessionFactory 实例。
同理可得,从数据源 ClusterDataSourceConfig 配置如下:
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
| @Configuration @MapperScan(basePackages = ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "clusterSqlSessionFactory") public class ClusterDataSourceConfig {
static final String PACKAGE = "com.clang.dao.cluster"; static final String MAPPER_LOCATION = "classpath:mapper/cluster/*.xml";
@Value("${cluster.datasource.url}") private String url;
@Value("${cluster.datasource.username}") private String user;
@Value("${cluster.datasource.password}") private String password;
@Value("${cluster.datasource.driverClassName}") private String driverClass;
@Bean(name = "clusterDataSource") public DataSource clusterDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driverClass); dataSource.setUrl(url); dataSource.setUsername(user); dataSource.setPassword(password); return dataSource; }
@Bean(name = "clusterTransactionManager") public DataSourceTransactionManager clusterTransactionManager() { return new DataSourceTransactionManager(clusterDataSource()); }
@Bean(name = "clusterSqlSessionFactory") public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("clusterDataSource") DataSource clusterDataSource) throws Exception { final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setDataSource(clusterDataSource); sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(ClusterDataSourceConfig.MAPPER_LOCATION)); return sessionFactoryBean.getObject(); } }
|
上面两组配置分别扫描 com.clang.dao.master(对应 classpath:mapper/master)和 com.clang.dao.cluster(对应 classpath:mapper/cluster)包中的 Mapper 接口。相关接口会由 MyBatis 通过容器管理,并在运行时解析对应 SQL。
代码下载