在开发中可能会遇到在一个项目中使用多个数据源的情况,我们可以使用springboot快速实现多数据源的配置。mybatis-plus的团队baomidou已经提供了一个开源项目dynamicDataSource方便实现多数据源的配置。这里就以springboot + mybatis-plus + dynamicDataSource实现多数据源的快速配置。
数据准备工作
创建数据库、表并添加数据,demo数据库和test数据库各有一张student表,其中都只有一条数据,student的name分别是他们的数据库名便于区分。
1.1 创建springboot项目,导入坐标。
pom文件如下,如果SQL文件写在resources目录下可以不用在build标签里面配置resource,否则要进行配置,不然在编译的时候就会忽略SQL文件导致报错。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>dynamic-datasource-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/mapper/**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
1.2 修改配置文件
mapper-locations配置的是SQL文件的位置,mybatis-plus不写SQL可以不用配置,但是碰到复杂的逻辑还是要写SQL,所以还是建议配上。
type是配置数据连接池的,这里采用的是alibaba的druid连接池,不配置就采用默认连接池,primary是默认数据源,一定要配置。
这里为了方便就使用本机mysql的不同数据库来实现,使用时根据实际情况自行更改。
spring:
datasource:
#使用druid连接池
type: com.alibaba.druid.pool.DruidDataSource
dynamic:
#设置默认的数据源或者数据源组,默认值即为master
primary: test
#严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
strict: false
datasource:
test:
url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
username: root
password: 1234
driver-class-name: com.mysql.cj.jdbc.Driver
demo:
url: jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
username: root
password: 1234
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:/com.demo.dynamicdatasourcedemo/mapper/**/*.xml
1.3 创建实体和接口
实体类和mapper接口如,一个Student实体、一个原生Mapper接口、两个加了DS注解切换数据源的Mapper接口。@DS是dynamicDataSource提供的注解,注解里面的值就是配置的数据源名称,填哪个数据源就会切换到哪个数据源,该注解可以用在类和方法上,同一个类下方法上的优先级比类高。
1.4 创建service
再创建一个StudentService用于调用不同的mapper接口查看其中的差异。
demo1在方法上加了DS注解切换demo数据源并且调用的是原生接口;
test1在方法上加了DS注解切换test数据源并且调用的是原生接口;
demo2在方法上加了DS注解切换test数据源并且调用的是demo数据源接口;
test2在方法上加了DS注解切换demo数据源并且调用的是test数据源接口;
package com.demo.dynamicdatasourcedemo.service;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.demo.dynamicdatasourcedemo.entity.Student;
import com.demo.dynamicdatasourcedemo.mapper.StudentMapper;
import com.demo.dynamicdatasourcedemo.mapper.demo.DemoStudentMapper;
import com.demo.dynamicdatasourcedemo.mapper.test.TestStudentMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class StudentService {
@Resource
private StudentMapper studentMapper;
@Resource
private TestStudentMapper testStudentMapper;
@Resource
private DemoStudentMapper demoStudentMapper;
@DS("demo")
public List<Student> getAllDemoStudent1() {
System.out.println("demo student 1 ...");
return studentMapper.selectList(null);
}
@DS("test")
public List<Student> getAllTestStudent1() {
System.out.println("test student 1 ...");
return studentMapper.selectList(null);
}
@DS("test")
public List<Student> getAllDemoStudent2() {
System.out.println("demo student 2 ...");
return demoStudentMapper.selectList(null);
}
@DS("demo")
public List<Student> getAllTestStudent2() {
System.out.println("test student 2 ...");
return testStudentMapper.selectList(null);
}
}
1.5 测试
在启动类中做一个简单的测试,从输出来看,很明显符合预期。service中的DS注解和mapper中的DS注解都可以生效,并且mapper中的优先级更高,优先级顺序:mapper方法>mapper类>service方法>service类。自此就已经使用springboot快速实现了数据源的切换。
1.6 自定义注解
dynamicDataSource在3.2.0版本之后支持自定义注解,要使用自定义注解需要继承DS。TestMapper用于切换test数据源,DemoMapper用于切换demo数据源。mapper类上使用自定义的注解,并且后面继承了DS。
1.7 测试自定义注解
从测试结果来看,自定义注解效果符合预期。