天天看點

多資料源配置MyBatisPlus(十八)

二八佳人體似酥,腰間仗劍斬愚夫。雖然不見人頭落,暗裡教君骨髓枯。

上一章簡單介紹了多資料源配置MyBatis(十七),如果沒有看過,​​請觀看上一章​​

工作中,在業務的發展或業務資料隔離的場景下,通常需要一個項目中引入多個資料源,

但SpringBoot預設的自動化配置是單資料源的,可以通過一些額外的配置,進行處理。

一. 多資料源配置前的工作準備

一.一 準備兩個資料庫 springboot 和springboot2

springboot 資料庫裡面存放着 user 表

springboot2 資料庫表裡面存放着 dept 表

-- 在 springboot 資料庫裡面 建立 user 表
use springboot;
CREATE TABLE `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(15) DEFAULT NULL,
    `sex` varchar(20) DEFAULT NULL,
    `age` int(6) DEFAULT NULL,
    `description` varchar(50) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

--  在 springboot2 資料庫裡面 建立 dept 表
use springboot2;
CREATE TABLE `dept` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(200) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;      

一.二 準備對應的實體 User.java 和 Dept.java

User.java

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    /**
     * @param id id編号
     * @param name 姓名
     * @param sex 性别
     * @param age 年齡
     * @param description 描述
     */
    private Integer id;
    private String name;
    private String sex;
    private Integer age;
    private String description;
}      

Dept.java

@Data
public class Dept {
    /**
     * @param id id編号
     * @param name 部門名稱
     */
    private Integer id;
    private String name;
}      

一.三 MyBatisPlus 的使用

關于 MyBatis 的使用,可以看老蝴蝶以前寫的文章: ​​SpringBoot整合MyBatisPlus(十四)​​

項目目錄:

多資料源配置MyBatisPlus(十八)

二. MyBatisPlus 多資料源配置

MyBatisPlus 的多資料源配置時,不用像 Jpa或者MyBatis 那樣,配置不同的DataSource 和 Factory.

與平常的 MyBatisPlus 開發基本一緻。

MyBatisPlus 提供了 一個插件 dynamic-datasource-spring-boot-starter ,可以友善我們進行多資料源配置。

具體可以見官網文檔: ​​MyBatisPlus多資料源​​

将其與 Druid 進行整合,切換資料源。

二.一 pom.xml 依賴

<!--引入springboot與mybatis-plus整合的依賴。 去掉mybatis的依賴-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>
        <!-- 引入pagehelper分頁插件  注意版本号要與 mybatis-plus 進行比對到 -->
         <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--引入動态資料源配置-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>      

二.二 application.yml 配置檔案

# 引入 資料庫的相關配置
#spring:
#  datasource:
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    url: jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true
#    username: root
#    password: abc123
# 配置成多資料源的形式
spring:
  autoconfigure:
    # 去掉Druid 配置   //第一部分點 
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  # 自動配置,例外處理
  datasource:
    # 配置資料源類型
    type: com.alibaba.druid.pool.DruidDataSource
    dynamic:
      primary: one #設定預設的資料源或者資料源組,預設值即為master。 為了統一,設定成one 
      strict: false #嚴格比對資料源,預設false. true未比對到指定資料源時抛異常,false使用預設資料源
      datasource:
        # 配置第一個資料庫
        one:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
          username: root
          password: abc123
        # 配置第二個資料庫
        two:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/springboot2?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
          username: root
          password: abc123
    druid:
      # 其他的 Druid 連接配接池配置資訊
      max-active: 30
      min-idle: 5
#整合mybatis時使用的
mybatis-plus:
  # 配置 mapper檔案的位置
  mapper-locations: classpath:mybatis/mapper/**/*Mapper.xml
  # 配置日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true #  配置别名設定
  global-config:
    db-config:
      logic-delete-field: flag   # 邏輯删除的字段
      logic-not-delete-value: 1  # 正常狀态下,該字段的值
      logic-delete-value: 0      # 删除後,該字段的值
      table-underline: true # 駝峰方式轉換
#分頁插件
pagehelper:
  helperDialect: mysql
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql      

注意,第一部分的内容,即 spring.autoconfigure.exclude 去掉了 Druid的自動配置。

如果在 yml 配置檔案中不去掉的話,那麼則需要在啟動類時進行去掉。

@MapperScan(value = "top.yueshushu.learn.mapper")
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})
public class MyBatisApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBatisApplication.class,args);
        System.out.println("運作 MybatisPlus 多資料源配置檔案");
    }
}      

注意,在啟動類上,加上 @MapperScan 掃描。 這個不要忘記了, Mybatis多資料源配置時,需要去掉。

二.三 實體配置

在 pojo 包下, 分别建立兩個包 one 和 two 包。

one 包下面放置所有使用 one 資料庫實體的資訊, two 包下面放置所有使用two資料庫實體的資訊

多資料源配置MyBatisPlus(十八)

二.三.一 User.java 使用者實體

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User implements Serializable {
    /**
     * @param id id編号
     * @param name 姓名
     * @param sex 性别
     * @param age 年齡
     * @param description 描述
     */
    @TableId(value = "id",type =IdType.AUTO)
    private Integer id;
    @TableField("name")
    private String name;
    @TableField("sex")
    private String sex;
    @TableField("age")
    private Integer age;
    @TableField("description")
    private String description;
}      

二.三.二 Dept.java 部門實體

@Data
@TableName("dept")
public class Dept implements Serializable {
    /**
     * @param id id編号
     * @param name 部門名稱
     */
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    @TableField("name")
    private String name;
}      

二.四 mapper 和其映射檔案 配置

在 mapper 包下, 建立 one 包和 two包

one 包下面放置所有使用 one 資料庫的資訊, two 包下面放置所有使用two資料庫的資訊

多資料源配置MyBatisPlus(十八)
多資料源配置MyBatisPlus(十八)

二. 四.一 UserMapper 和其映射檔案

二.四.一.一 UserMapper.java 接口

//掃描由啟動類進行掃描配置
public interface UserMapper extends BaseMapper<User> {
    //一個走 xml的方法
    void batchAdd(@Param("userList") List<User> userList);
}      

二.四.一.二 UserMapper.xml 映射檔案

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.yueshushu.learn.mapper.mapper1.UserMapper">
    <insert id="batchAdd">
        insert into user(name,sex,age,description) values
        <foreach collection="userList" item="user" open="" close="" separator=",">
            (#{user.name},#{user.sex},#{user.age},#{user.description})
        </foreach>
    </insert>
</mapper>      

二.四.二 DeptMapper 和其映射檔案

二.四.二.一 DeptMapper.java 接口

//掃描由啟動類進行掃描配置
public interface DeptMapper extends BaseMapper<Dept> {
    //走 xml 的配置
    void batchAdd(@Param("deptList") List<Dept> deptList);
}      

二.四.二.二 DeptMapper.xml 映射檔案

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.yueshushu.learn.mapper.mapper2.DeptMapper">
    <insert id="batchAdd">
        insert into dept(name) values
        <foreach collection="deptList" item="user" open="" close="" separator=",">
            (#{user.name})
        </foreach>
    </insert>
</mapper>      

二.五 接口及其實作

多資料源配置MyBatisPlus(十八)

注意,在實作類上或者實作類的方法上,添加 @DS(“資料庫的别名”) 的注解資訊

二.五.一 UserService接口和其實作類

UserService.java

public interface UserService {
    void batchAddUser(List<User> userList);
    List<User> listUser();
    //查詢 springboot2 資料庫的方法
    List<Dept> listDept();
}      

UserServiceImpl.java 實作類

@Service
//在類上添加注解,表示類中所有的方法都走這個資料源。
@DS("one")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DeptMapper deptMapper;

    @Override
    public void batchAddUser(List<User> userList) {
        userMapper.batchAdd(userList);
    }
    @Override
    public List<User> listUser() {
       return userMapper.selectList(null);
    }
    //在方法上添加注解,表示這個方法走定義的資料源
    @DS("two")
    @Override
    public List<Dept> listDept() {
        return deptMapper.selectList(null);
    }
}      

@DS(“資料庫别名”) 注解到類上, 表示這個類中的所有的方法都預設走這個資料庫。如果不填寫的話,表示走預設配置的那個資料庫。

注解到方法上,表示這個方法單獨走自定義的資料庫。 優先級比類上的注解高。

二.五.二 DeptService接口和其實作類

DeptService.java

public interface DeptService {
    void batchAddDept(List<Dept> deptList);
    List<Dept> listDept();
    //走 springboot 資料庫的方法
    List<User> listUser();
}      

DeptServiceImpl.java

@Service
//采用 springboot2 的資料庫
@DS("two")
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private UserMapper userMapper;
    @Override
    public void batchAddDept(List<Dept> deptList) {
        deptMapper.batchAdd(deptList);
    }
    @Override
    public List<Dept> listDept() {
       return deptMapper.selectList(null);
    }
    //單獨另外采用 springboot 的資料庫
    @DS("one")
    @Override
    public List<User> listUser() {
        return userMapper.selectList(null);
    }

}      

二.六 測試

二.六. 一 測試類編寫

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
@Log4j2
public class MyBatisPlusTests {
    @Autowired
    private UserService userService;
    @Autowired
    private DeptService deptService;
    @Test
    public void addUserTest(){
        //1. 建構對象
        User user=new User();
        user.setName("小歡歡");
        user.setAge(22);
        user.setSex("女");
        user.setDescription("一個小壞蛋");

        User user1=new User();
        user1.setName("小澤霖");
        user1.setAge(25);
        user1.setSex("男");
        user1.setDescription("一個大壞蛋");

        //這是修改的操作,id=2已經存在這條記錄了。
        User user2=new User();
        user2.setName("嶽澤霖");
        user2.setAge(25);
        user2.setSex("男性");
        user2.setDescription("一個快樂的程式員");

        //2. 放置到集合裡面
        List<User> userList=new ArrayList<>();
        userList.add(user);
        userList.add(user1);
        userList.add(user2);
        userService.batchAddUser(userList);
    }

    @Test
    public void listUserTest(){
        System.out.println("User實作類:>>>>>>>>>>>查詢員工");
        List<User> userList=userService.listUser();
        userList.forEach(n->log.info(n));
        System.out.println("User實作類:>>>>>>>>>>>>查詢部門");
        List<Dept> deptList=userService.listDept();
        deptList.forEach(n->log.info(n));
    }
    @Test
    public void addDeptTest(){
        //1. 建構對象
        Dept dept=new Dept();
        dept.setName("資訊管理部");
        Dept dept1=new Dept();
        dept1.setName("研發部");
        Dept dept2=new Dept();
        dept2.setName("測試部");
        //2. 放置到集合裡面
        List<Dept> deptList=new ArrayList<>();
        deptList.add(dept);
        deptList.add(dept1);
        deptList.add(dept2);
        deptService.batchAddDept(deptList);
        log.info("添加部門成功");
    }

    @Test
    public void listDeptTest(){
        System.out.println("Dept實作類:>>>>>>>查詢部門");
        List<Dept> deptList=deptService.listDept();
        deptList.forEach(n->log.info(n));
        System.out.println("Dept實作類:>>>>>>>>>>>查詢員工");
        List<User> userList=deptService.listUser();
        userList.forEach(n->log.info(n));
    }
    /**
     * 資料源切換配置
     */
    @Test
    public void allDataSourceTest(){
        addUserTest();
        listDeptTest();
        addDeptTest();
        listUserTest();
    }
}      

二.六.二 測試

員工的批量添加 和部門的批量添加

員工 addUserTest

多資料源配置MyBatisPlus(十八)

對應 的資料庫裡面有相應的資訊:

多資料源配置MyBatisPlus(十八)

部門 addDeptTest

多資料源配置MyBatisPlus(十八)

對應的資料庫裡面的資訊

多資料源配置MyBatisPlus(十八)

進行查詢

User實作類 進行查詢 listUserTest

多資料源配置MyBatisPlus(十八)

Dept實作類 進行查詢 listDeptTest

多資料源配置MyBatisPlus(十八)

同時切換資料源 allDataSourceTest

也是成功的,資料表裡面也有相應的資料。 (太多,老蝴蝶就不截圖了)

本章節的代碼放置在 github 上: