Mybatis Plus配置多数据源

打印 上一主题 下一主题

主题 801|帖子 801|积分 2403

概述

该项目重要描述了Mybatis Plus多数据源的配置和使用,此中详细记录的配置过程,整个过程从数据库表的创建到数据初始化都有详细的记录说明。
别的,如果存在同一个表在多个数据源中都存在的情况,有一些注意事项,下面看文章通过例子说明。
详细步骤

by-mybatis-plus项目一

不同的表在不同的数据源中,不存在同一个表在多个数据源的情况。
数据库脚本



  • 在数据库1:database1中新建数据库表,并插入初始化数据
  1. CREATE DATABASE `datasource1` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
  2. use `datasource1`;
  3. CREATE TABLE `user_info` (
  4.     `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
  5.     `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
  6.     `user_sex` TINYINT(2) NOT NULL COMMENT '用户性别(0 女性 1男性 2其他)',
  7.     `user_age` INT NOT NULL COMMENT '用户年龄',
  8.     `user_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户地址',
  9.     `ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
  10.     `mtime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  11.     PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户信息表';
  13. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('张三', 1, 18, '北京');
  14. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('张颜', 0, 18, '乌鲁木齐');
  15. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('李四', 1, 12, '上海');
  16. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('王五', 1, 18, '北京');
  17. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('王武', 1, 23, '北京');
  18. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('王媛', 0, 43, '成都');
  19. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('李康', 1, 36, '广州');
  20. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('王梅', 0, 16, '合肥');
  21. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('李雪华', 0, 23, '东京');
  22. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('张熏然', 0, 19, '纽约');
  23. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('何莉莉', 0, 32, '深圳');
  24. INSERT INTO `datasource1`.`user_info` (`user_name`, `user_sex`, `user_age`, `user_address`) VALUES ('李茉', 0, 23, '东莞');
复制代码


  • 在数据库2:database2中新建数据库表,并插入初始化数据
  1. CREATE DATABASE `datasource2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
  2. use `datasource2`;
  3. CREATE TABLE `user_login_log` (
  4.     `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
  5.     `user_id` bigint NOT NULL COMMENT '登录用户id',
  6.     `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
  7.     `activity_type` varchar(255) NOT NULL COMMENT '活动时间:in登入,out登出',
  8.     `activity_trigger_time` timestamp NOT NULL COMMENT '不懂触发时间(登录或者登出时间)',
  9.     `ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
  10.     `mtime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  11.     PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户登录信息记录表';
  13. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (1, '张三', 'in', '2024-08-06 16:38:43');
  14. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (1, '张三', 'out', '2024-08-06 16:39:43');
  15. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (1, '张三', 'in', '2024-08-06 16:48:43');
  16. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (1, '张三', 'out', '2024-08-06 16:59:43');
  17. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (2, '李四', 'in', '2024-08-06 16:38:43');
  18. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (2, '李四', 'out', '2024-08-06 16:39:43');
  19. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (2, '李四', 'in', '2024-08-06 16:48:43');
  20. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (2, '李四', 'out', '2024-08-06 16:59:43');
  21. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'in', '2024-08-06 16:38:43');
  22. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'out', '2024-08-06 16:39:43');
  23. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'in', '2024-08-06 16:48:43');
  24. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'out', '2024-08-06 16:59:43');
  25. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'in', '2024-08-06 17:38:43');
  26. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'out', '2024-08-06 17:39:43');
  27. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'in', '2024-08-06 18:48:43');
  28. INSERT INTO `datasource2`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (3, '王五', 'out', '2024-08-06 18:59:43');
复制代码
添加maven依靠

  1. <dependencies>
  2.     <dependency>
  3.         <groupId>com.baomidou</groupId>
  4.         <artifactId>mybatis-plus-boot-starter</artifactId>
  5.         <version>3.5.1</version>
  6.     </dependency>
  7.    
  8.     <dependency>
  9.         <groupId>com.baomidou</groupId>
  10.         <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  11.         <version>3.5.1</version>
  12.     </dependency>
  13. </dependencies>
复制代码
编写配置文件

  1. spring:
  2.   datasource:
  3.     dynamic:
  4.       primary: datasource1 #设置默认的数据源或者数据源组,默认值即为datasource1
  5.       strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
  6.       datasource:
  7.         datasource1:
  8.           url: jdbc:mysql://127.0.0.1:33060/datasource1?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false
  9.           username: root
  10.           password: root
  11.           driver-class-name: com.mysql.cj.jdbc.Driver
  12.         datasource2:
  13.           url: jdbc:mysql://127.0.0.1:33060/datasource2?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false
  14.           username: root
  15.           password: root
  16.           driver-class-name: com.mysql.cj.jdbc.Driver
复制代码
在 service类 和 mapper类 上添加数据源注解



  • 数据源1:datasource1
  1. @Mapper
  2. @DS("datasource1")
  3. public interface UserInfoMapper extends BaseMapper<UserInfo> {
  4. }
复制代码
  1. @Service
  2. @DS("datasource1")
  3. public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
  4. }
复制代码


  • 数据源2:datasource2
  1. @Mapper
  2. @DS("datasource2")
  3. public interface UserLoginLogMapper extends BaseMapper<UserLoginLog> {
  4. }
复制代码
  1. @Service
  2. @DS("datasource2")
  3. public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, UserLoginLog> implements UserLoginLogService {
  4. }
复制代码
编写业务代码

  1. @Controller
  2. public class BasicController {
  3.     @Resource
  4.     private UserInfoService userInfoService;
  5.     @Resource
  6.     private UserLoginLogService userLoginLogService;
  7.     private static final String LOGIN = "in";
  8.     // http://127.0.0.1:8080/get/user/login/info?id=1
  9.     @RequestMapping("/get/user/login/info")
  10.     @ResponseBody
  11.     public String getUserLoginInfo(@RequestParam(name = "id", required = true) String id) {
  12.         UserInfo one = userInfoService.lambdaQuery().eq(UserInfo::getId, id).one();
  13.         System.out.println("查询到id=" + id + "的登录用户信息:" + one);
  14.         List<UserLoginLog> list = userLoginLogService.lambdaQuery()
  15.                 .eq(Objects.nonNull(one), UserLoginLog::getUserId, one.getId())
  16.                 .eq(UserLoginLog::getActivityType, LOGIN)
  17.                 .list();
  18.         System.out.println("查询到id=" + id + "的用户一共登录了:" + list.size() + "次");
  19.         return "用户id= " + id + ",名叫:" + one.getUserName() + ",一共登录了系统" + list.size() + "次";
  20.     }
  21. }
复制代码
启动服务、通过浏览器调用接口

哀求 http://127.0.0.1:8080/get/user/login/info?id=1 ,查看执行结果

by-mybatis-plus项目二

某一个表存在于多个数据源中,即本项目中user_login_log表既在datasource1中又在datasource2中,UserLoginLogService在查询的时间既必要从datasource1又必要从datasource2中查询数据
数据库脚本

在数据库1中补充user_login_log表,并初始化数据
  1. use `datasource1`;
  2. CREATE TABLE `user_login_log` (
  3.     `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
  4.     `user_id` bigint NOT NULL COMMENT '登录用户id',
  5.     `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
  6.     `activity_type` varchar(255) NOT NULL COMMENT '活动时间:in登入,out登出',
  7.     `activity_trigger_time` timestamp NOT NULL COMMENT '不懂触发时间(登录或者登出时间)',
  8.     `ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
  9.     `mtime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  10.     PRIMARY KEY (`id`)
  11. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户登录信息记录表';
  12. INSERT INTO `datasource1`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (1, '张三', 'in', '2024-08-06 16:38:43');
  13. INSERT INTO `datasource1`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (1, '张三', 'out', '2024-08-06 16:59:43');
  14. INSERT INTO `datasource1`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (2, '李四', 'in', '2024-08-06 16:38:43');
  15. INSERT INTO `datasource1`.`user_login_log` (`user_id`, `user_name`, `activity_type`, `activity_trigger_time`) VALUES (2, '李四', 'out', '2024-08-06 16:39:43');
复制代码
在多数据源库的表user_login_log对应的mapper.java上取消@DS(“datasource2”)注解

  1. @Mapper
  2. // @DS("datasource2")
  3. public interface UserLoginLogMapper extends BaseMapper<UserLoginLog> {
  4. }
复制代码
在多数据源的表user_login_log对应的service中添加方法,方法必要指定使用的数据源

  1. @Service
  2. @DS("datasource2")
  3. public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, UserLoginLog> implements UserLoginLogService {
  4.     @DS("datasource2")
  5.     @Override
  6.     public List<UserLoginLog> getDataSource(long userId, String activityType) {
  7.         return lambdaQuery().eq(UserLoginLog::getUserId, userId).eq(UserLoginLog::getActivityType, activityType).list();
  8.     }
  9.     @DS("datasource1")
  10.     @Override
  11.     public List<UserLoginLog> getAntherDataSource(long userId, String activityType) {
  12.         return lambdaQuery().eq(UserLoginLog::getUserId, userId).eq(UserLoginLog::getActivityType, activityType).list();
  13.     }
  14. }
复制代码
注:由于uer_login_log该表在datasource1和datasource2数据源中都存在,所以在mapper.java中必要取消@DS注解


  • 那么在service的方法中就必要指定数据源
  • 在service的上层调用方如controller中必须调用service的方法,不能跳过service类中方法而直接在controller中通过
    userLoginLogService.lambdaQuery()的方式调用,这样调用体系会直接查询yml配置的"primary: datasource1"的默认数据源
编写controller类测试

  1. @Controller
  2. public class BasicController {
  3.     @Resource
  4.     private UserInfoService userInfoService;
  5.     @Resource
  6.     private UserLoginLogService userLoginLogService;
  7.     private static final String LOGIN = "in";
  8.     /**
  9.      * 说明: 该方法中通过mybatis plus的多数据源调用两个库的数据查询
  10.      * userInfoService使用数据源datasource1
  11.      * userLoginLogService使用数据源datasource2
  12.      * 测试请求地址: <a href="http://127.0.0.1:8080/get/user/login/info?id=1">测试请求地址</a>
  13.      *
  14.      * @param id 用户id
  15.      * @return 查询结果
  16.      */
  17.     @RequestMapping("/get/user/login/info")
  18.     @ResponseBody
  19.     public String getUserLoginInfo(@RequestParam(name = "id") Long id) {
  20.         UserInfo one = userInfoService.lambdaQuery().eq(UserInfo::getId, id).one();
  21.         System.out.println("查询到id=" + id + "的登录用户信息:" + one);
  22.         /*
  23.          * 如果在userLoginLogService中有方法指定了@DS其他数据源,那么在上层方法中不能跳过userLoginLogService的方法
  24.          * 直接使用lambdaQuery(),只能在userLoginLogService中使用lambdaQuery(),因为如果直接使用lambdaQuery()的话,
  25.          * 因为mapper.java没有配置数据源(原因见下个方法注释),会直接使用yml配置的primary: datasource1数据源
  26.          */
  27.         List<UserLoginLog> list = userLoginLogService.lambdaQuery()
  28.                 .eq(Objects.nonNull(one), UserLoginLog::getUserId, one.getId())
  29.                 .eq(UserLoginLog::getActivityType, LOGIN)
  30.                 .list();
  31.         System.out.println("lambdaQuery()方式查询到id=" + id + "的用户一共登录了:" + list.size() + "次");
  32.         List<UserLoginLog> dataSource = userLoginLogService.getDataSource(one.getId(), LOGIN);
  33.         System.out.println("调用service中方法的方式查询到id=" + id + "的用户一共登录了:" + dataSource.size() + "次");
  34.         return "用户id= " + id + ",名叫:" + one.getUserName() + ",一共登录了系统" + dataSource.size() + "次";
  35.     }
  36.     /**
  37.      * 说明:该方法中通过mybatis plus的多数据源调用两个库的数据查询,其中且有一个库在两边都存在并进行查询
  38.      * userInfoService 配置数据源datasource1
  39.      * userLoginLogService 默认配置数据源datasource2,但是在某些方法上使用数据源datasource1
  40.      * 测试请求地址: <a href="http://127.0.0.1:8080/get/different/in/same/service?id=1">测试请求地址</a>
  41.      *
  42.      * @param id 用户id
  43.      * @return 查询结果
  44.      */
  45.     @RequestMapping("/get/different/in/same/service")
  46.     @ResponseBody
  47.     public String getDifferentInInSameService(@RequestParam(name = "id") Long id) {
  48.         UserInfo one = userInfoService.lambdaQuery().eq(UserInfo::getId, id).one();
  49.         System.out.println("查询到id=" + id + "的登录用户信息:" + one);
  50.         /*
  51.          * 重要!!!
  52.          * 说明,如果在某个service中有方法使用其他数据源,那么注意:
  53.          * 1、在mapper.java中不能使用@DS注解,如果使用,所有的请求都会走mapper.java中指定的数据源
  54.          * 2、在service中,需要走默认数据源的方法,需要手动编写方法,不能在层如controller中直接通过lambdaQuery()方式调用,否则会和另外指定数据源的方法走一个数据源去
  55.          */
  56. //        List<UserLoginLog> list = userLoginLogService.lambdaQuery()
  57. //                .eq(Objects.nonNull(one), UserLoginLog::getUserId, one.getId())
  58. //                .eq(UserLoginLog::getActivityType, LOGIN)
  59. //                .list();
  60.         List<UserLoginLog> list = userLoginLogService.getDataSource(id, LOGIN);
  61.         System.out.println("database2登录:" + list.size() + "次");
  62.         List<UserLoginLog> antherDataSource = userLoginLogService.getAntherDataSource(id, LOGIN);
  63.         System.out.println("database1登录:" + antherDataSource.size() + "次");
  64.         int size = list.size() + antherDataSource.size();
  65.         System.out.println("查询到id=" + id + "的用户一共登录了:" + size + "次");
  66.         return "用户id= " + id + ",名叫:" + one.getUserName() + ",一共登录了系统" + size + "次";
  67.     }
  68. }
复制代码
启动服务、进行测试

哀求 http://127.0.0.1:8080/get/user/login/info?id=1 ,查看执行结果

idea配景打印日志:

哀求 http://127.0.0.1:8080/get/different/in/same/service?id=1 ,查看执行结果

idea配景打印日志:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小秦哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表