diff --git a/spring-boot-demo-multi-datasource-mybatis/README.md b/spring-boot-demo-multi-datasource-mybatis/README.md new file mode 100644 index 0000000..9543ab2 --- /dev/null +++ b/spring-boot-demo-multi-datasource-mybatis/README.md @@ -0,0 +1,382 @@ +# spring-boot-demo-multi-datasource-mybatis + +> 此 demo 主要演示了 Spring Boot 如何集成 Mybatis 的多数据源。可以自己基于AOP实现多数据源,这里基于 Mybatis-Plus 提供的一个优雅的开源的解决方案来实现。 + +## 准备工作 + +准备两个数据源,分别执行如下建表语句 + +```mysql +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; +``` + +## 导入依赖 + +```xml + + + 4.0.0 + + spring-boot-demo-multi-datasource-mybatis + 1.0.0-SNAPSHOT + jar + + spring-boot-demo-multi-datasource-mybatis + Demo project for Spring Boot + + + com.xkcoding + spring-boot-demo + 1.0.0-SNAPSHOT + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + mysql + mysql-connector-java + + + + com.baomidou + dynamic-datasource-spring-boot-starter + 2.5.0 + + + + com.baomidou + mybatis-plus-boot-starter + 3.0.7.1 + + + + org.projectlombok + lombok + true + + + + cn.hutool + hutool-all + + + + com.google.guava + guava + + + + + spring-boot-demo-multi-datasource-mybatis + + + org.springframework.boot + spring-boot-maven-plugin + + + + + +``` + +## 准备实体类 + +`User.java` + +> 1. @Data / @NoArgsConstructor / @AllArgsConstructor / @Builder 都是 lombok 注解 +> 2. @TableName("multi_user") 是 Mybatis-Plus 注解,主要是当实体类名字和表名不满足 **驼峰和下划线互转** 的格式时,用于表示数据库表名 +> 3. @TableId(type = IdType.ID_WORKER) 是 Mybatis-Plus 注解,主要是指定主键类型,这里我使用的是 Mybatis-Plus 基于 twitter 提供的 雪花算法 + +```java +/** + *

+ * User实体类 + *

+ * + * @package: com.xkcoding.multi.datasource.mybatis.model + * @description: User实体类 + * @author: yangkai.shen + * @date: Created in 2019-01-21 14:19 + * @copyright: Copyright (c) 2019 + * @version: V1.0 + * @modified: yangkai.shen + */ +@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 就拥有了大部分单表操作的方法了。 + +```java +/** + *

+ * 数据访问层 + *

+ * + * @package: com.xkcoding.multi.datasource.mybatis.mapper + * @description: 数据访问层 + * @author: yangkai.shen + * @date: Created in 2019-01-21 14:28 + * @copyright: Copyright (c) 2019 + * @version: V1.0 + * @modified: yangkai.shen + */ +public interface UserMapper extends BaseMapper { +} +``` + +## 数据服务层 + +### 接口 + +`UserService.java` + +```java +/** + *

+ * 数据服务层 + *

+ * + * @package: com.xkcoding.multi.datasource.mybatis.service + * @description: 数据服务层 + * @author: yangkai.shen + * @date: Created in 2019-01-21 14:31 + * @copyright: Copyright (c) 2019 + * @version: V1.0 + * @modified: yangkai.shen + */ +public interface UserService extends IService { + + /** + * 添加 User + * + * @param user 用户 + */ + void addUser(User user); +} +``` + +### 实现 + +`UserServiceImpl.java` + +> 1. @DS: 注解在类上或方法上来切换数据源,方法上的@DS优先级大于类上的@DS +> 2. baseMapper: mapper 对象,即`UserMapper`,可获得CRUD功能 +> 3. 默认走从库: `@DS(value = "slave")`在类上,默认走从库,除非在方法在添加`@DS(value = "master")`才走主库 + +```java +/** + *

+ * 数据服务层 实现 + *

+ * + * @package: com.xkcoding.multi.datasource.mybatis.service.impl + * @description: 数据服务层 实现 + * @author: yangkai.shen + * @date: Created in 2019-01-21 14:37 + * @copyright: Copyright (c) 2019 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Service +@DS("slave") +public class UserServiceImpl extends ServiceImpl implements UserService { + + /** + * 类上 {@code @DS("slave")} 代表默认从库,在方法上写 {@code @DS("master")} 代表默认主库 + * + * @param user 用户 + */ + @DS("master") + @Override + public void addUser(User user) { + baseMapper.insert(user); + } +} +``` + +## 启动类 + +`SpringBootDemoMultiDatasourceMybatisApplication.java` + +> 启动类上方需要使用@MapperScan扫描 mapper 类所在的包 + +```java +/** + *

+ * 启动器 + *

+ * + * @package: com.xkcoding.multi.datasource.mybatis + * @description: 启动器 + * @author: yangkai.shen + * @date: Created in 2019-01-21 14:19 + * @copyright: Copyright (c) 2019 + * @version: V1.0 + * @modified: yangkai.shen + */ +@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` + +```yaml +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 +``` + +## 测试类 + +```java +/** + *

+ * 测试主从数据源 + *

+ * + * @package: com.xkcoding.multi.datasource.mybatis.service.impl + * @description: 测试主从数据源 + * @author: yangkai.shen + * @date: Created in 2019-01-21 14:45 + * @copyright: Copyright (c) 2019 + * @version: V1.0 + * @modified: yangkai.shen + */ +@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 list = userService.list(new QueryWrapper<>()); + log.info("【list】= {}", JSONUtil.toJsonStr(list)); + } +} +``` + +### 测试结果 + +主从数据源加载成功 + +```java +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** 操作 + +![image-20190121153211509](assets/image-20190121153211509.png) + +**从**库 **建议** 只执行 **SELECT** 操作 + +![image-20190121152825859](assets/image-20190121152825859.png) + +> 生产环境需要搭建 **主从复制** + +## 参考 + +1. Mybatis-Plus 多数据源文档:https://mybatis.plus/guide/dynamic-datasource.html +2. Mybatis-Plus 多数据源集成官方 demo:https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter/tree/master/samples \ No newline at end of file diff --git a/spring-boot-demo-multi-datasource-mybatis/assets/image-20190121152825859.png b/spring-boot-demo-multi-datasource-mybatis/assets/image-20190121152825859.png new file mode 100644 index 0000000..d2bfc89 Binary files /dev/null and b/spring-boot-demo-multi-datasource-mybatis/assets/image-20190121152825859.png differ diff --git a/spring-boot-demo-multi-datasource-mybatis/assets/image-20190121153211509.png b/spring-boot-demo-multi-datasource-mybatis/assets/image-20190121153211509.png new file mode 100644 index 0000000..51830ae Binary files /dev/null and b/spring-boot-demo-multi-datasource-mybatis/assets/image-20190121153211509.png differ