Skip to content

Commit a4b63c3

Browse files
committed
✨ spring-boot-demo-multi-datasource-mybatis 完成
1 parent f68cd7f commit a4b63c3

File tree

3 files changed

+382
-0
lines changed

3 files changed

+382
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
# spring-boot-demo-multi-datasource-mybatis
2+
3+
> 此 demo 主要演示了 Spring Boot 如何集成 Mybatis 的多数据源。可以自己基于AOP实现多数据源,这里基于 Mybatis-Plus 提供的一个优雅的开源的解决方案来实现。
4+
5+
## 准备工作
6+
7+
准备两个数据源,分别执行如下建表语句
8+
9+
```mysql
10+
DROP TABLE IF EXISTS `multi_user`;
11+
CREATE TABLE `multi_user`(
12+
`id` bigint(64) NOT NULL,
13+
`name` varchar(50) DEFAULT NULL,
14+
`age` int(30) DEFAULT NULL,
15+
PRIMARY KEY (`id`) USING BTREE
16+
) ENGINE = InnoDB
17+
AUTO_INCREMENT = 1
18+
CHARACTER SET = utf8
19+
COLLATE = utf8_general_ci;
20+
```
21+
22+
## 导入依赖
23+
24+
```xml
25+
<?xml version="1.0" encoding="UTF-8"?>
26+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
27+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
28+
<modelVersion>4.0.0</modelVersion>
29+
30+
<artifactId>spring-boot-demo-multi-datasource-mybatis</artifactId>
31+
<version>1.0.0-SNAPSHOT</version>
32+
<packaging>jar</packaging>
33+
34+
<name>spring-boot-demo-multi-datasource-mybatis</name>
35+
<description>Demo project for Spring Boot</description>
36+
37+
<parent>
38+
<groupId>com.xkcoding</groupId>
39+
<artifactId>spring-boot-demo</artifactId>
40+
<version>1.0.0-SNAPSHOT</version>
41+
</parent>
42+
43+
<properties>
44+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
45+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
46+
<java.version>1.8</java.version>
47+
</properties>
48+
49+
<dependencies>
50+
<dependency>
51+
<groupId>org.springframework.boot</groupId>
52+
<artifactId>spring-boot-starter</artifactId>
53+
</dependency>
54+
55+
<dependency>
56+
<groupId>org.springframework.boot</groupId>
57+
<artifactId>spring-boot-starter-test</artifactId>
58+
<scope>test</scope>
59+
</dependency>
60+
61+
<dependency>
62+
<groupId>mysql</groupId>
63+
<artifactId>mysql-connector-java</artifactId>
64+
</dependency>
65+
66+
<dependency>
67+
<groupId>com.baomidou</groupId>
68+
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
69+
<version>2.5.0</version>
70+
</dependency>
71+
72+
<dependency>
73+
<groupId>com.baomidou</groupId>
74+
<artifactId>mybatis-plus-boot-starter</artifactId>
75+
<version>3.0.7.1</version>
76+
</dependency>
77+
78+
<dependency>
79+
<groupId>org.projectlombok</groupId>
80+
<artifactId>lombok</artifactId>
81+
<optional>true</optional>
82+
</dependency>
83+
84+
<dependency>
85+
<groupId>cn.hutool</groupId>
86+
<artifactId>hutool-all</artifactId>
87+
</dependency>
88+
89+
<dependency>
90+
<groupId>com.google.guava</groupId>
91+
<artifactId>guava</artifactId>
92+
</dependency>
93+
</dependencies>
94+
95+
<build>
96+
<finalName>spring-boot-demo-multi-datasource-mybatis</finalName>
97+
<plugins>
98+
<plugin>
99+
<groupId>org.springframework.boot</groupId>
100+
<artifactId>spring-boot-maven-plugin</artifactId>
101+
</plugin>
102+
</plugins>
103+
</build>
104+
105+
</project>
106+
```
107+
108+
## 准备实体类
109+
110+
`User.java`
111+
112+
> 1. @Data / @NoArgsConstructor / @AllArgsConstructor / @Builder 都是 lombok 注解
113+
> 2. @TableName("multi_user") 是 Mybatis-Plus 注解,主要是当实体类名字和表名不满足 **驼峰和下划线互转** 的格式时,用于表示数据库表名
114+
> 3. @TableId(type = IdType.ID_WORKER) 是 Mybatis-Plus 注解,主要是指定主键类型,这里我使用的是 Mybatis-Plus 基于 twitter 提供的 雪花算法
115+
116+
```java
117+
/**
118+
* <p>
119+
* User实体类
120+
* </p>
121+
*
122+
* @package: com.xkcoding.multi.datasource.mybatis.model
123+
* @description: User实体类
124+
* @author: yangkai.shen
125+
* @date: Created in 2019-01-21 14:19
126+
* @copyright: Copyright (c) 2019
127+
* @version: V1.0
128+
* @modified: yangkai.shen
129+
*/
130+
@Data
131+
@TableName("multi_user")
132+
@NoArgsConstructor
133+
@AllArgsConstructor
134+
@Builder
135+
public class User implements Serializable {
136+
private static final long serialVersionUID = -1923859222295750467L;
137+
138+
/**
139+
* 主键
140+
*/
141+
@TableId(type = IdType.ID_WORKER)
142+
private Long id;
143+
144+
/**
145+
* 姓名
146+
*/
147+
private String name;
148+
149+
/**
150+
* 年龄
151+
*/
152+
private Integer age;
153+
}
154+
```
155+
156+
## 数据访问层
157+
158+
`UserMapper.java`
159+
160+
> 不需要建对应的xml,只需要继承 BaseMapper 就拥有了大部分单表操作的方法了。
161+
162+
```java
163+
/**
164+
* <p>
165+
* 数据访问层
166+
* </p>
167+
*
168+
* @package: com.xkcoding.multi.datasource.mybatis.mapper
169+
* @description: 数据访问层
170+
* @author: yangkai.shen
171+
* @date: Created in 2019-01-21 14:28
172+
* @copyright: Copyright (c) 2019
173+
* @version: V1.0
174+
* @modified: yangkai.shen
175+
*/
176+
public interface UserMapper extends BaseMapper<User> {
177+
}
178+
```
179+
180+
## 数据服务层
181+
182+
### 接口
183+
184+
`UserService.java`
185+
186+
```java
187+
/**
188+
* <p>
189+
* 数据服务层
190+
* </p>
191+
*
192+
* @package: com.xkcoding.multi.datasource.mybatis.service
193+
* @description: 数据服务层
194+
* @author: yangkai.shen
195+
* @date: Created in 2019-01-21 14:31
196+
* @copyright: Copyright (c) 2019
197+
* @version: V1.0
198+
* @modified: yangkai.shen
199+
*/
200+
public interface UserService extends IService<User> {
201+
202+
/**
203+
* 添加 User
204+
*
205+
* @param user 用户
206+
*/
207+
void addUser(User user);
208+
}
209+
```
210+
211+
### 实现
212+
213+
`UserServiceImpl.java`
214+
215+
> 1. @DS: 注解在类上或方法上来切换数据源,方法上的@DS优先级大于类上的@DS
216+
> 2. baseMapper: mapper 对象,即`UserMapper`,可获得CRUD功能
217+
> 3. 默认走从库: `@DS(value = "slave")`在类上,默认走从库,除非在方法在添加`@DS(value = "master")`才走主库
218+
219+
```java
220+
/**
221+
* <p>
222+
* 数据服务层 实现
223+
* </p>
224+
*
225+
* @package: com.xkcoding.multi.datasource.mybatis.service.impl
226+
* @description: 数据服务层 实现
227+
* @author: yangkai.shen
228+
* @date: Created in 2019-01-21 14:37
229+
* @copyright: Copyright (c) 2019
230+
* @version: V1.0
231+
* @modified: yangkai.shen
232+
*/
233+
@Service
234+
@DS("slave")
235+
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
236+
237+
/**
238+
* 类上 {@code @DS("slave")} 代表默认从库,在方法上写 {@code @DS("master")} 代表默认主库
239+
*
240+
* @param user 用户
241+
*/
242+
@DS("master")
243+
@Override
244+
public void addUser(User user) {
245+
baseMapper.insert(user);
246+
}
247+
}
248+
```
249+
250+
## 启动类
251+
252+
`SpringBootDemoMultiDatasourceMybatisApplication.java`
253+
254+
> 启动类上方需要使用@MapperScan扫描 mapper 类所在的包
255+
256+
```java
257+
/**
258+
* <p>
259+
* 启动器
260+
* </p>
261+
*
262+
* @package: com.xkcoding.multi.datasource.mybatis
263+
* @description: 启动器
264+
* @author: yangkai.shen
265+
* @date: Created in 2019-01-21 14:19
266+
* @copyright: Copyright (c) 2019
267+
* @version: V1.0
268+
* @modified: yangkai.shen
269+
*/
270+
@SpringBootApplication
271+
@MapperScan(basePackages = "com.xkcoding.multi.datasource.mybatis.mapper")
272+
public class SpringBootDemoMultiDatasourceMybatisApplication {
273+
274+
public static void main(String[] args) {
275+
SpringApplication.run(SpringBootDemoMultiDatasourceMybatisApplication.class, args);
276+
}
277+
278+
}
279+
```
280+
281+
## 配置文件
282+
283+
`application.yml`
284+
285+
```yaml
286+
spring:
287+
datasource:
288+
dynamic:
289+
datasource:
290+
master:
291+
username: root
292+
password: root
293+
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
294+
driver-class-name: com.mysql.cj.jdbc.Driver
295+
slave:
296+
username: root
297+
password: root
298+
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
299+
driver-class-name: com.mysql.cj.jdbc.Driver
300+
mp-enabled: true
301+
logging:
302+
level:
303+
com.xkcoding.multi.datasource.mybatis: debug
304+
```
305+
306+
## 测试类
307+
308+
```java
309+
/**
310+
* <p>
311+
* 测试主从数据源
312+
* </p>
313+
*
314+
* @package: com.xkcoding.multi.datasource.mybatis.service.impl
315+
* @description: 测试主从数据源
316+
* @author: yangkai.shen
317+
* @date: Created in 2019-01-21 14:45
318+
* @copyright: Copyright (c) 2019
319+
* @version: V1.0
320+
* @modified: yangkai.shen
321+
*/
322+
@Slf4j
323+
public class UserServiceImplTest extends SpringBootDemoMultiDatasourceMybatisApplicationTests {
324+
@Autowired
325+
private UserService userService;
326+
327+
/**
328+
* 主从库添加
329+
*/
330+
@Test
331+
public void addUser() {
332+
User userMaster = User.builder().name("主库添加").age(20).build();
333+
userService.addUser(userMaster);
334+
335+
User userSlave = User.builder().name("从库添加").age(20).build();
336+
userService.save(userSlave);
337+
}
338+
339+
/**
340+
* 从库查询
341+
*/
342+
@Test
343+
public void testListUser() {
344+
List<User> list = userService.list(new QueryWrapper<>());
345+
log.info("【list】= {}", JSONUtil.toJsonStr(list));
346+
}
347+
}
348+
```
349+
350+
### 测试结果
351+
352+
主从数据源加载成功
353+
354+
```java
355+
2019-01-21 14:55:41.096 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : master - Starting...
356+
2019-01-21 14:55:41.307 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : master - Start completed.
357+
2019-01-21 14:55:41.308 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : slave - Starting...
358+
2019-01-21 14:55:41.312 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : slave - Start completed.
359+
2019-01-21 14:55:41.312 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 初始共加载 2 个数据源
360+
2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 动态数据源-加载 slave 成功
361+
2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 动态数据源-加载 master 成功
362+
2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 当前的默认数据源是单数据源,数据源名为 master
363+
_ _ |_ _ _|_. ___ _ | _
364+
| | |\/|_)(_| | |_\ |_)||_|_\
365+
/ |
366+
3.0.7.1
367+
```
368+
369+
******建议** 只执行 **INSERT** **UPDATE** **DELETE** 操作
370+
371+
![image-20190121153211509](assets/image-20190121153211509.png)
372+
373+
******建议** 只执行 **SELECT** 操作
374+
375+
![image-20190121152825859](assets/image-20190121152825859.png)
376+
377+
> 生产环境需要搭建 **主从复制**
378+
379+
## 参考
380+
381+
1. Mybatis-Plus 多数据源文档:https://mybatis.plus/guide/dynamic-datasource.html
382+
2. Mybatis-Plus 多数据源集成官方 demo:https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter/tree/master/samples
Loading
Loading

0 commit comments

Comments
 (0)