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 9.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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. * @author yangkai.shen
  99. * @date Created in 2019-01-21 14:19
  100. */
  101. @Data
  102. @TableName("multi_user")
  103. @NoArgsConstructor
  104. @AllArgsConstructor
  105. @Builder
  106. public class User implements Serializable {
  107. private static final long serialVersionUID = -1923859222295750467L;
  108. /**
  109. * 主键
  110. */
  111. @TableId(type = IdType.ID_WORKER)
  112. private Long id;
  113. /**
  114. * 姓名
  115. */
  116. private String name;
  117. /**
  118. * 年龄
  119. */
  120. private Integer age;
  121. }
  122. ```
  123. ## 数据访问层
  124. `UserMapper.java`
  125. > 不需要建对应的xml,只需要继承 BaseMapper 就拥有了大部分单表操作的方法了。
  126. ```java
  127. /**
  128. * <p>
  129. * 数据访问层
  130. * </p>
  131. *
  132. * @author yangkai.shen
  133. * @date Created in 2019-01-21 14:28
  134. */
  135. public interface UserMapper extends BaseMapper<User> {
  136. }
  137. ```
  138. ## 数据服务层
  139. ### 接口
  140. `UserService.java`
  141. ```java
  142. /**
  143. * <p>
  144. * 数据服务层
  145. * </p>
  146. *
  147. * @author yangkai.shen
  148. * @date Created in 2019-01-21 14:31
  149. */
  150. public interface UserService extends IService<User> {
  151. /**
  152. * 添加 User
  153. *
  154. * @param user 用户
  155. */
  156. void addUser(User user);
  157. }
  158. ```
  159. ### 实现
  160. `UserServiceImpl.java`
  161. > 1. @DS: 注解在类上或方法上来切换数据源,方法上的@DS优先级大于类上的@DS
  162. > 2. baseMapper: mapper 对象,即`UserMapper`,可获得CRUD功能
  163. > 3. 默认走从库: `@DS(value = "slave")`在类上,默认走从库,除非在方法在添加`@DS(value = "master")`才走主库
  164. ```java
  165. /**
  166. * <p>
  167. * 数据服务层 实现
  168. * </p>
  169. *
  170. * @author yangkai.shen
  171. * @date Created in 2019-01-21 14:37
  172. */
  173. @Service
  174. @DS("slave")
  175. public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
  176. /**
  177. * 类上 {@code @DS("slave")} 代表默认从库,在方法上写 {@code @DS("master")} 代表默认主库
  178. *
  179. * @param user 用户
  180. */
  181. @DS("master")
  182. @Override
  183. public void addUser(User user) {
  184. baseMapper.insert(user);
  185. }
  186. }
  187. ```
  188. ## 启动类
  189. `SpringBootDemoMultiDatasourceMybatisApplication.java`
  190. > 启动类上方需要使用@MapperScan扫描 mapper 类所在的包
  191. ```java
  192. /**
  193. * <p>
  194. * 启动器
  195. * </p>
  196. *
  197. * @author yangkai.shen
  198. * @date Created in 2019-01-21 14:19
  199. */
  200. @SpringBootApplication
  201. @MapperScan(basePackages = "com.xkcoding.multi.datasource.mybatis.mapper")
  202. public class SpringBootDemoMultiDatasourceMybatisApplication {
  203. public static void main(String[] args) {
  204. SpringApplication.run(SpringBootDemoMultiDatasourceMybatisApplication.class, args);
  205. }
  206. }
  207. ```
  208. ## 配置文件
  209. `application.yml`
  210. ```yaml
  211. spring:
  212. datasource:
  213. dynamic:
  214. datasource:
  215. master:
  216. username: root
  217. password: root
  218. 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
  219. driver-class-name: com.mysql.cj.jdbc.Driver
  220. slave:
  221. username: root
  222. password: root
  223. 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
  224. driver-class-name: com.mysql.cj.jdbc.Driver
  225. mp-enabled: true
  226. logging:
  227. level:
  228. com.xkcoding.multi.datasource.mybatis: debug
  229. ```
  230. ## 测试类
  231. ```java
  232. /**
  233. * <p>
  234. * 测试主从数据源
  235. * </p>
  236. *
  237. * @author yangkai.shen
  238. * @date Created in 2019-01-21 14:45
  239. */
  240. @Slf4j
  241. public class UserServiceImplTest extends SpringBootDemoMultiDatasourceMybatisApplicationTests {
  242. @Autowired
  243. private UserService userService;
  244. /**
  245. * 主从库添加
  246. */
  247. @Test
  248. public void addUser() {
  249. User userMaster = User.builder().name("主库添加").age(20).build();
  250. userService.addUser(userMaster);
  251. User userSlave = User.builder().name("从库添加").age(20).build();
  252. userService.save(userSlave);
  253. }
  254. /**
  255. * 从库查询
  256. */
  257. @Test
  258. public void testListUser() {
  259. List<User> list = userService.list(new QueryWrapper<>());
  260. log.info("【list】= {}", JSONUtil.toJsonStr(list));
  261. }
  262. }
  263. ```
  264. ### 测试结果
  265. 主从数据源加载成功
  266. ```java
  267. 2019-01-21 14:55:41.096 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : master - Starting...
  268. 2019-01-21 14:55:41.307 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : master - Start completed.
  269. 2019-01-21 14:55:41.308 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : slave - Starting...
  270. 2019-01-21 14:55:41.312 INFO 7239 --- [ main] com.zaxxer.hikari.HikariDataSource : slave - Start completed.
  271. 2019-01-21 14:55:41.312 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 初始共加载 2 个数据源
  272. 2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 动态数据源-加载 slave 成功
  273. 2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 动态数据源-加载 master 成功
  274. 2019-01-21 14:55:41.313 INFO 7239 --- [ main] c.b.d.d.DynamicRoutingDataSource : 当前的默认数据源是单数据源,数据源名为 master
  275. _ _ |_ _ _|_. ___ _ | _
  276. | | |\/|_)(_| | |_\ |_)||_|_\
  277. / |
  278. 3.0.7.1
  279. ```
  280. **主**库 **建议** 只执行 **INSERT** **UPDATE** **DELETE** 操作
  281. ![image-20190121153211509](http://static.xkcoding.com/spring-boot-demo/multi-datasource/mybatis/063506.jpg)
  282. **从**库 **建议** 只执行 **SELECT** 操作
  283. ![image-20190121152825859](http://static.xkcoding.com/spring-boot-demo/multi-datasource/mybatis/063505.jpg)
  284. > 生产环境需要搭建 **主从复制**
  285. ## 参考
  286. 1. Mybatis-Plus 多数据源文档:https://mybatis.plus/guide/dynamic-datasource.html
  287. 2. Mybatis-Plus 多数据源集成官方 demo:https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter/tree/master/samples