spring-boot-demo-multi-datasource-mybatis
https://gitee.com/xkcoding/spring-boot-demo
此 demo 主要演示了 Spring Boot 如何集成 Mybatis 的多数据源。可以自己基于AOP实现多数据源,这里基于 Mybatis-Plus 提供的一个优雅的开源的解决方案来实现。
准备工作
准备两个数据源,分别执行如下建表语句
1 2 3 4 5 6 7 8 9 10
| DROP TABLE IF EXISTS `multi_user`; CREATE TABLE `multi_user`( `id` bigint(64) NOT NULL, `name` varchar(50) DEFAULT NULL, `age` int(30) DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci;
|
导入依赖
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 74 75 76 77 78 79 80 81
| <?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>
<artifactId>spring-boot-demo-multi-datasource-mybatis</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging>
<name>spring-boot-demo-multi-datasource-mybatis</name> <description>Demo project for Spring Boot</description>
<parent> <groupId>com.xkcoding</groupId> <artifactId>spring-boot-demo</artifactId> <version>1.0.0-SNAPSHOT</version> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>2.5.0</version> </dependency>
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.7.1</version> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </dependency>
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> </dependencies>
<build> <finalName>spring-boot-demo-multi-datasource-mybatis</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
</project>
|
准备实体类
User.java
- @Data / @NoArgsConstructor / @AllArgsConstructor / @Builder 都是 lombok 注解
- @TableName(“multi_user”) 是 Mybatis-Plus 注解,主要是当实体类名字和表名不满足 驼峰和下划线互转 的格式时,用于表示数据库表名
- @TableId(type = IdType.ID_WORKER) 是 Mybatis-Plus 注解,主要是指定主键类型,这里我使用的是 Mybatis-Plus 基于 twitter 提供的 雪花算法
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
|
@Data @TableName("multi_user") @NoArgsConstructor @AllArgsConstructor @Builder public class User implements Serializable { private static final long serialVersionUID = -1923859222295750467L;
@TableId(type = IdType.ID_WORKER) private Long id;
private String name;
private Integer age; }
|
数据访问层
UserMapper.java
不需要建对应的xml,只需要继承 BaseMapper 就拥有了大部分单表操作的方法了。
1 2 3 4 5 6 7 8 9 10
|
public interface UserMapper extends BaseMapper<User> { }
|
数据服务层
接口
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public interface UserService extends IService<User> {
void addUser(User user); }
|
实现
UserServiceImpl.java
- @DS: 注解在类上或方法上来切换数据源,方法上的@DS优先级大于类上的@DS
- baseMapper: mapper 对象,即
UserMapper
,可获得CRUD功能
- 默认走从库:
@DS(value = "slave")
在类上,默认走从库,除非在方法在添加@DS(value = "master")
才走主库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
@Service @DS("slave") public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@DS("master") @Override public void addUser(User user) { baseMapper.insert(user); } }
|
启动类
SpringBootDemoMultiDatasourceMybatisApplication.java
启动类上方需要使用@MapperScan扫描 mapper 类所在的包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
@SpringBootApplication @MapperScan(basePackages = "com.xkcoding.multi.datasource.mybatis.mapper") public class SpringBootDemoMultiDatasourceMybatisApplication {
public static void main(String[] args) { SpringApplication.run(SpringBootDemoMultiDatasourceMybatisApplication.class, args); }
}
|
配置文件
application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| spring: datasource: dynamic: datasource: master: username: root password: root url: jdbc:mysql://127.0.0.1:3306/spring-boot-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8 driver-class-name: com.mysql.cj.jdbc.Driver slave: username: root password: root url: jdbc:mysql://127.0.0.1:3306/spring-boot-demo-2?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8 driver-class-name: com.mysql.cj.jdbc.Driver mp-enabled: true logging: level: com.xkcoding.multi.datasource.mybatis: debug
|
测试类
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
|
@Slf4j public class UserServiceImplTest extends SpringBootDemoMultiDatasourceMybatisApplicationTests { @Autowired private UserService userService;
@Test public void addUser() { User userMaster = User.builder().name("主库添加").age(20).build(); userService.addUser(userMaster);
User userSlave = User.builder().name("从库添加").age(20).build(); userService.save(userSlave); }
@Test public void testListUser() { List<User> list = userService.list(new QueryWrapper<>()); log.info("【list】= {}", JSONUtil.toJsonStr(list)); } }
|
测试结果
主从数据源加载成功
1 2 3 4 5 6 7 8 9 10 11 12
| 2019-01-21 14:55:41.096 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : master - Starting... 2019-01-21 14:55:41.307 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : master - Start completed. 2019-01-21 14:55:41.308 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : slave - Starting... 2019-01-21 14:55:41.312 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : slave - Start completed. 2019-01-21 14:55:41.312 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 初始共加载 2 个数据源 2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 动态数据源-加载 slave 成功 2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 动态数据源-加载 master 成功 2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 当前的默认数据源是单数据源,数据源名为 master _ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.0.7.1
|
主库 建议 只执行 INSERT UPDATE DELETE 操作

从库 建议 只执行 SELECT 操作

生产环境需要搭建 主从复制
参考
- Mybatis-Plus 多数据源文档:https://mybatis.plus/guide/dynamic-datasource.html
- Mybatis-Plus 多数据源集成官方 demo:https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter/tree/master/samples