druid+mybatis配置多数据源同时生效 – 多数据源(一)
应用场景
- 多数据源对应的表可能不同
- 每个数据库维护自己的数据
- 每个数据源维护自己对应的mapper
- 本质上是一连多,并没有==切换==数据源
实现
引入依赖
环境为springboot2.7.5
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
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- mybatis 支持 SpringBoot --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.16</version> </dependency> <!--引用 log4j2 spring boot 启动器,内部依赖了 slf4j、log4j;排除项目中的 logback--> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> <version>3.0.3</version> </dependency>
|
mapper和xml
分别对应不同的mapper,需要映射对应的mapper接口,person可以换成不同的实体类和表
master.xml
1
| <mapper namespace="com.example.demo.mapper.master.PersonMapper0">
|
cluster.xml
1
| <mapper namespace="com.example.demo.mapper.master.PersonMapper1">
|
xml文件放在对应resources
的mapping
目录下
PersonMapper0.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Mapper //表示这是Mybatis的mapper类 @Repository public interface PersonMapper0 {
List<Person> queryUserList();
Person queryUserByID(String id);
int addUser(Person person);
int updateUser(Person person);
int deleteUser(String id);
}
|
配置文件
需要自定义两个(多个)数据源的配置项,这里只列举了基础属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| spring: datasource: db01: # 指定数据源 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型 # 1.jdbc配置 url: jdbc:mysql://localhost:3306/demo1 username: root password: xxxxxx #2.连接池配置 #初始化连接池的连接数量 大小,最小,最大 initial-size: 5 db02: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型 # 1.jdbc配置 url: jdbc:mysql://localhost:3306/demo2 username: root password: xxxxxx #2.连接池配置 #初始化连接池的连接数量 大小,最小,最大 initial-size: 5
|
数据库配置类
数据库连接相关,以及扫描实体和mapper
主数据库master
配置类
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 69 70 71 72 73
| import com.alibaba.druid.pool.DruidDataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource; import java.sql.SQLException;
@Configuration @MapperScan(basePackages = MasterDbConfig.PACKAGE , sqlSessionFactoryRef = "masterSqlSessionFactory") public class MasterDbConfig { private Logger logger = LoggerFactory.getLogger(MasterDbConfig.class); // 精确到 master 目录,以便跟其他数据源隔离 static final String PACKAGE = "com.example.demo.mapper.master"; private static final String MAPPER_LOCATION = "classpath*:mapping/master/*.xml"; private static final String DOMAIN_PACKAGE = "com.example.demo.entity";
@Value("${spring.datasource.db01.url}") private String dbUrl;
@Value("${spring.datasource.db01.username}") private String username;
@Value("${spring.datasource.db01.password}") private String password;
@Value("${spring.datasource.db01.driver-class-name}") private String driverClassName;
@Bean(name="masterDataSource") //声明其为Bean实例 @Primary //在同样的DataSource中,首先使用被标注的DataSource public DataSource masterDataSource() { DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl); datasource.setUsername(username); datasource.setPassword(password); datasource.setDriverClassName(driverClassName);
return datasource; }
@Bean(name = "masterTransactionManager") @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(MasterDbConfig.MAPPER_LOCATION)); sessionFactory.setTypeAliasesPackage(DOMAIN_PACKAGE); //mybatis 数据库字段与实体类属性驼峰映射配置 sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true); return sessionFactory.getObject(); } }
|
从数据库Cluster
配置类
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 69 70 71 72
| package com.example.demo.config;
import com.alibaba.druid.pool.DruidDataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource; import java.sql.SQLException;
/** * 从数据源配置 * 若需要配置更多数据源 , 直接在yml中添加数据源配置再增加相应的新的数据源配置类即可 */ @Configuration @MapperScan(basePackages = ClusterDbConfig.PACKAGE , sqlSessionFactoryRef = "clusterSqlSessionFactory") public class ClusterDbConfig { private Logger logger = LoggerFactory.getLogger(ClusterDbConfig.class); // 精确到 cluster 目录,以便跟其他数据源隔离 static final String PACKAGE = "com.example.demo.mapper.cluster"; private static final String MAPPER_LOCATION = "classpath*:mapping/cluster/*.xml"; private static final String DOMAIN_PACKAGE = "com.example.demo.entity";
@Value("${spring.datasource.db02.url}") private String dbUrl;
@Value("${spring.datasource.db02.username}") private String username;
@Value("${spring.datasource.db02.password}") private String password;
@Value("${spring.datasource.db02.driver-class-name}") private String driverClassName;
@Bean(name="clusterDataSource") //声明其为Bean实例 public DataSource clusterDataSource() { DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl); datasource.setUsername(username); datasource.setPassword(password); datasource.setDriverClassName(driverClassName); return datasource; }
@Bean(name = "clusterTransactionManager") public DataSourceTransactionManager clusterTransactionManager() { return new DataSourceTransactionManager(clusterDataSource()); }
@Bean(name = "clusterSqlSessionFactory") public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("clusterDataSource") DataSource culsterDataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(culsterDataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(ClusterDbConfig.MAPPER_LOCATION)); sessionFactory.setTypeAliasesPackage(DOMAIN_PACKAGE); //mybatis 数据库字段与实体类属性驼峰映射配置 sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true); return sessionFactory.getObject(); } }
|
测试访问
启动项目后会看到有两个datasource连接池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @CrossOrigin @RestController @RequestMapping("/define") public class DemoController { @Autowired PersonMapper0 pMapperMaster;
@GetMapping("/pMapperMaster") public List<Person> pMapperMaster() { List<Person> users = pMapperMaster.queryUserList(); return users; }
@Autowired PersonMapper1 pMapperCluster;
@GetMapping("/pMapperCluster") public List<Person> pMapperCluster() { List<Person> users = pMapperCluster.queryUserList(); return users; } }
|
访问结果
两个数据源的数据不同