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 候选时,该 Bean 优先被考虑。「多数据源配置的时候注意,必须要有一个主数据源,用 @Primary 标志该 Bean」
@MapperScan 扫描 Mapper 接口并容器管理,包路径精确到 master,为了和下面 cluster 数据源做到精确区分 @Value 获取全局配置文件 application.properties 的 kv 配置,并自动装配 sqlSessionFactoryRef 表示定义了 key ,表示一个唯一 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(); } }
|
上面数据配置分别扫描 Mapper 接口,com.clang.dao.master(对应 xml classpath:mapper/master ) 和 com.clang.dao.cluster(对应 xml classpath:mapper/cluster ) 包中对应的 UserDAO 和 CityDAO 。 都有 @Mapper 标志为 Mybatis 的并通过容器管理的 Bean。Mybatis 内部会使用反射机制运行去解析相应 SQL。
代码下载