You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 11 kB

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

一个用来深度学习并实战 spring boot 的项目,目前总共包含 66 个集成demo,已经完成 55 个。