SpringBoot + MyBatis使用多数据源
有时候我们需要在一个项目里面集成一个或者多个数据源。
实现的思想
- 使用
mybatis
持久层框架 mybatis
的运行需要依赖于几个组件DataSource
数据源DataSourceTransactionManager
事务管理器SqlSessionFactory
SqlSession工厂,负责创建SqlSessionSqlSessionTemplate
SqlSession,负责执行crud
- 多数据源,就是使用多个数据源,多个事务管理器,多个SqlSession工厂,就有不同的SqlSession
Maven
使用Druid作为数据源
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.14</version>
</dependency>
</dependencies>
application.yml
配置多个数据源,这里仅仅配置了基本必须的属性
logging:
level:
root: debug
datasource:
1:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot1?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&serverTimezone=GMT%2b8
username: root
password: root
2:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&serverTimezone=GMT%2b8
username: root
password: root
多个数据源的@Configuration 配置
第一个数据源以及持久层需要的组件
package io.springboot.multidatasource.configuration;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource;
@Configuration
public class DataSourceConfiguration1 {
@Bean(name = "dataSource1")
@Primary
@ConfigurationProperties(prefix = "datasource.1")
public DataSource dataSource() {
return new DruidDataSource();
}
@Bean(name = "dataSourceTransactionManager1")
@Primary
public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource1")DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "sqlSessionFactory1")
@Primary
public SqlSessionFactory sessionFactory(@Qualifier("dataSource1")DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean.getObject();
}
@Bean("sqlSessionTemplate1")
@Primary
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
第二个数据源以及持久层需要的组件
package io.springboot.multidatasource.configuration;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource;
@Configuration
public class DataSourceConfiguration2 {
@Bean(name = "dataSource2")
@ConfigurationProperties(prefix = "datasource.2")
public DataSource dataSource() {
return new DruidDataSource();
}
@Bean(name = "dataSourceTransactionManager2")
public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource2")DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "sqlSessionFactory2")
public SqlSessionFactory sessionFactory(@Qualifier("dataSource2")DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean.getObject();
}
@Bean("sqlSessionTemplate2")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
可以看到,配置1中的bean,比配置2中的bean多了一个 @Primary
注解。
当其他的组件通过@Autowired等方式注入一个类的时候。而IOC中有多个该的实现。那么标注了@Primary
注解的Bean会优先注入。详细可以参阅官方文档
Main
package io.springboot.multidatasource;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.annotation.MapperScans;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScans(value = {
@MapperScan(basePackages = "io.springboot.multidatasource.mapper1",
sqlSessionFactoryRef = "sqlSessionFactory1",sqlSessionTemplateRef = "sqlSessionTemplate1"),
@MapperScan(basePackages = "io.springboot.multidatasource.mapper2",
sqlSessionFactoryRef = "sqlSessionFactory2",sqlSessionTemplateRef = "sqlSessionTemplate2"),
})
public class MultidatasourceApplication {
public static void main(String[] args) {
SpringApplication.run(MultidatasourceApplication.class, args);
}
}
重点在于 @MapperScan
注解。该注解会去扫描指定包下的接口。并且动态的生成实现类。
通过 sqlSessionFactoryRe
f 和 sqlSessionTemplateRef
指定它们生成代理对象时。使用的SqlSessionFactory 和 SqlSession。(值就是定义在了IOC中的bean名称)。