1. 程式人生 > 程式設計 >Spring Boot + Mybatis-Plus實現多資料來源的方法

Spring Boot + Mybatis-Plus實現多資料來源的方法

前段時間寫了一篇基於mybatis實現的多資料來源部落格。感覺不是很好,這次打算加入git,來搭建一個基於Mybatis-Plus的多資料來源專案
Mybatis-Plus就是香

前言:該專案分為master資料來源與local資料來源。假定master資料來源為線上資料庫,local為本地資料庫。後續我們將通過xxl-job的方式,將線上(master)中的資料同步到本地(local)中

專案git地址 抽時間把專案提交到git倉庫,方便大家直接克隆
sql檔案已置於專案中,資料庫使用的mysql

建立專案

我這裡使用的idea,正常建立spring boot專案就行了。

sql

-- 建立master資料庫
CREATE DATABASE db_master;

USE db_master;
-- 使用者表
CREATE TABLE users(
	id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主鍵id',username VARCHAR(20) NOT NULL COMMENT '使用者名稱',pwd VARCHAR(50) NOT NULL COMMENT '密碼',phone CHAR(11) NOT NULL COMMENT '手機號',email VARCHAR(50) COMMENT '郵箱',gender CHAR(1) COMMENT '性別 1-->男 0-->女',age INT COMMENT '年齡',created_time TIMESTAMP NULL DEFAULT NULL COMMENT '建立時間',updated_time TIMESTAMP NULL DEFAULT NULL COMMENT '修改時間',deleted_time TIMESTAMP NULL DEFAULT NULL COMMENT '刪除時間',type INT DEFAULT 1 COMMENT '狀態 1-->啟用 2-->禁用 3-->軟刪除'
)ENGINE=INNODB;

INSERT INTO users(username,pwd,phone,email,gender,age) VALUES('supperAdmin','admin123','13000000000','[email protected]',1,20); 
INSERT INTO users(username,age) VALUES('admin','admin','13200840033','[email protected]',14); 
INSERT INTO users(username,age) VALUES('wanggang','wanggang','13880443322','[email protected]',36); 
INSERT INTO users(username,age) VALUES('xiaobao','xiaobao','18736450102','[email protected]',22); 
INSERT INTO users(username,age) VALUES('zhaoxing','zhaoxing','18966004400','[email protected]',29); 
INSERT INTO users(username,age) VALUES('chenyun','chenyun','13987613540','[email protected]',25); 
INSERT INTO users(username,age) VALUES('ouyangruixue','ouyangruixue','15344773322','[email protected]',24); 

-- 建立local資料庫
CREATE DATABASE db_local;

USE db_local;
-- 本地庫使用者表
CREATE TABLE users(
	id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主鍵id',type INT DEFAULT 1 COMMENT '狀態 1-->啟用 2-->禁用 3-->軟刪除'
)ENGINE=INNODB;
-- 本地庫測試表
CREATE TABLE local_test(
	id INT PRIMARY KEY AUTO_INCREMENT,str VARCHAR(20)
)ENGINE=INNODB;
INSERT INTO local_test(str) VALUES ('Hello');
INSERT INTO local_test(str) VALUES ('World');
INSERT INTO local_test(str) VALUES ('Mysql');
INSERT INTO local_test(str) VALUES ('^.^');

pom檔案

目前只引入了lombok、mybatis-plus、mysql相關的依賴

	<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
		<!-- lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <!-- Mybatis-Plus -->
    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.2.0</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
    </dependency>

application.yml

properties刪除,yml建立。其實無所謂yml還是properties

server:
 port: 8001

spring:
 datasource:
  master:
   url: jdbc:mysql://localhost:3306/db_master?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
   username: root
   password: 123456
   driver-class-name: com.mysql.cj.jdbc.Driver

  local:
   url: jdbc:mysql://localhost:3306/db_local?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
   username: root
   password: 123456
   driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
 mapper-locations: classpath:mappers/*/*Mapper.xml
 #實體掃描,多個package用逗號或者分號分隔
 typeAliasesPackage: com.niuniu.sys.module
 check-config-location: true
 configuration:
  #是否開啟自動駝峰命名規則(camel case)對映
  map-underscore-to-camel-case: true
  #全域性地開啟或關閉配置檔案中的所有對映器已經配置的任何快取
  cache-enabled: false
  call-setters-on-nulls: true
  #配置JdbcTypeForNull,oracle資料庫必須配置
  jdbc-type-for-null: 'null'
  #MyBatis 自動對映時未知列或未知屬性處理策略 NONE:不做任何處理 (預設值),WARNING:以日誌的形式列印相關警告資訊,FAILING:當作對映失敗處理,並丟擲異常和詳細資訊
  auto-mapping-unknown-column-behavior: warning
 global-config:
  banner: false
  db-config:
   #主鍵型別 0:"資料庫ID自增",1:"未設定主鍵型別",2:"使用者輸入ID (該型別可以通過自己註冊自動填充外掛進行填充)",3:"全域性唯一ID (idWorker),4:全域性唯一ID (UUID),5:字串全域性唯一ID (idWorker 的字串表示)";
   id-type: auto
   #欄位驗證策略 IGNORED:"忽略判斷",NOT_NULL:"非NULL判斷",NOT_EMPTY:"非空判斷",DEFAULT 預設的,一般只用於註解裡(1. 在全局裡代表 NOT_NULL,2. 在註解裡代表 跟隨全域性)
   field-strategy: NOT_EMPTY
   #資料庫大寫下劃線轉換
   capital-mode: true
   #邏輯刪除值
   logic-delete-value: 0
   #邏輯未刪除值
   logic-not-delete-value: 1

pagehelper:            #pagehelper分頁外掛
 helperDialect: mysql     #設定資料庫方言
 reasonable: true
 supportMethodsArguments: true
 params: count=countSql

目錄結構

由於該專案分為兩個資料來源。在各個分層中,你將分別見到master、local。

在這裡插入圖片描述

備註:由於users表在兩個資料來源中完全相同,將Users實體置於model層公用

關鍵程式碼

在config包中,我們需要對master、local的資料來源進行配置,使其可以通過不同的請求,自動切換資料來源

另外 由於該專案使用mybatis-plus,在建立SqlSessionFactory的時候,請使用MybatisSqlSessionFactoryBean進行bean物件的建立

在這裡插入圖片描述

local資料來源

package com.demo.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "com.demo.dao.local",sqlSessionFactoryRef = "localSqlSessionFactory")
public class LocalDataSourceConfig {
  @Value("${spring.datasource.local.driver-class-name}")
  private String driverClassName;
  @Value("${spring.datasource.local.url}")
  private String url;
  @Value("${spring.datasource.local.username}")
  private String username;
  @Value("${spring.datasource.local.password}")
  private String password;

  @Bean(name = "localDataSource")
  public DataSource localDataSource() {
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    dataSource.setJdbcUrl(url);
    dataSource.setDriverClassName(driverClassName);
    dataSource.setMaximumPoolSize(10);
    dataSource.setMinimumIdle(5);
    dataSource.setPoolName("localDataSourcePool");
    return dataSource;
  }

  /**
   * local資料來源
   */
  @Bean(name = "localSqlSessionFactory")
  public SqlSessionFactory sqlSessionFactory(@Qualifier("localDataSource") DataSource dataSource) throws Exception {
    MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    // 設定Mybatis全域性配置路徑
    bean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
    bean.setMapperLocations(
        new PathMatchingResourcePatternResolver().getResources("classpath*:mappers/local/*.xml"));
    return bean.getObject();
  }

  @Bean(name = "localTransactionManager")
  public DataSourceTransactionManager transactionManager(@Qualifier("localDataSource") DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
  }

  @Bean(name = "localSqlSessionTemplate")
  public SqlSessionTemplate testSqlSessionTemplate(
      @Qualifier("localSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

master資料來源

package com.demo.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "com.demo.dao.master",sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {
  @Value("${spring.datasource.master.driver-class-name}")
  private String driverClassName;
  @Value("${spring.datasource.master.url}")
  private String url;
  @Value("${spring.datasource.master.username}")
  private String username;
  @Value("${spring.datasource.master.password}")
  private String password;

  @Bean(name = "masterDataSource")
  @Primary
  public DataSource masterDataSource() {
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    dataSource.setJdbcUrl(url);
    dataSource.setDriverClassName(driverClassName);
    dataSource.setMaximumPoolSize(10);
    dataSource.setMinimumIdle(5);
    dataSource.setPoolName("masterDataSource");
    return dataSource;
  }


  /**
   * master資料來源
   */
  @Bean(name = "masterSqlSessionFactory")
  @Primary
  public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
    MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
    bean.setMapperLocations(
        new PathMatchingResourcePatternResolver().getResources("classpath*:mappers/master/*.xml"));
    return bean.getObject();
  }

  @Bean(name = "masterTransactionManager")
  @Primary
  public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
  }

  @Bean(name = "masterSqlSessionTemplate")
  @Primary
  public SqlSessionTemplate testSqlSessionTemplate(
      @Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

部分程式碼

Users實體類

package com.demo.model;

import lombok.Data;
import java.util.Date;

@Data
public class Users {
  private Integer id;
  private String username;
  private String pwd;
  private String phone;
  private String email;
  private Integer gender;
  private Integer age;
  private Date created_time;
  private Date updated_time;
  private Date deleted_time;
  private Integer type;
}

UsersMapper

package com.demo.dao.master;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.demo.model.Users;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UsersMapper extends BaseMapper<Users> {
}

UsersService

package com.demo.service.master;

import com.baomidou.mybatisplus.extension.service.IService;
import com.demo.model.Users;

public interface UsersService extends IService<Users> {
}

UsersServiceImpl

package com.demo.service.master.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.dao.master.UsersMapper;
import com.demo.model.Users;
import com.demo.service.master.UsersService;
import org.springframework.stereotype.Service;

@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper,Users> implements UsersService {
}

UsersController

package com.demo.controller.master;

import com.demo.model.Users;
import com.demo.service.master.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/master")
public class UsersController {
  @Autowired
  private UsersService userssService;
  
  @RequestMapping("/users")
  public List<Users> list() {
    return userssService.list();
  }
}

最終的專案結構

在這裡插入圖片描述

執行結果

在這裡插入圖片描述
在這裡插入圖片描述

至此Spring Boot + Mybatis-Plus已經完成了多資料來源的實現。
最後再寫一點我遇到的坑吧
1、master與local中不要出現同名的檔案
2、資料來源配置中SqlSessionFactoryBean替換為MybatisSqlSessionFactoryBean

下一篇將會圍繞xxl-job任務排程中心,介紹如何通過xxl-job實現本地庫與線上庫的定時同步

到此這篇關於Spring Boot + Mybatis-Plus實現多資料來源的文章就介紹到這了,更多相關Spring Boot Mybatis-Plus多資料來源內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!