Java實戰(zhàn)系列(1):SpringBoot+ShardingSphere實現(xiàn)多數(shù)據(jù)源切換

主要組件版本信息:

SpringBoot:2.2.8.RELEASE

MyBatis Plus:3.3.2

ShardingSphere:4.0.0-RC2

需求說明

在企業(yè)開發(fā)中,如果業(yè)務數(shù)據(jù)分布在不同的數(shù)據(jù)源,那么我們就希望在訪問業(yè)務數(shù)據(jù)的時候,能夠根據(jù)業(yè)務需求,動態(tài)地切換數(shù)據(jù)源,ShardingSphere是一款不錯的數(shù)據(jù)庫中間件,利用它,可以很方便地實現(xiàn)我們想要的功能,下面,我們從零開始介紹,項目搭建及多數(shù)據(jù)源切換實現(xiàn)。

技術選型

Java 8 + MySql 5.7+ SpringBoot + Lombok + Mybatis Plus + ShardingSphere

開發(fā)工具:IntelliJ IDEA + Navicat

SpringBoot項目搭建

打開IDEA,新建一個SpringBoot 項目,如下圖示:

創(chuàng)建項目

創(chuàng)建項目2
填寫項目元數(shù)據(jù)

填寫完項目元數(shù)據(jù),點擊Next繼續(xù)下一步,
引入組件,確定版本號
指定項目名和路徑
由以上步驟可以看到,用IDEA搭建SpringBoots項目非常方便。

項目創(chuàng)建完成后,我們來看下整體目錄結(jié)構,如下圖示:


目錄結(jié)構

我們調(diào)整下pom.xml,改成如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dgd</groupId>
    <artifactId>multi-datasource</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>multi-datasource</name>
    <description>多數(shù)據(jù)源切換</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <springboot.version>2.2.8.RELEASE</springboot.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${springboot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${springboot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <version>${springboot.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

spring-boot-starter是SpringBoot項目的核心,必須要引入;spring-boot-starter-web提供了web相關功能,而spring-boot-starter-test是SpringBoot的測試組件,后續(xù)我們寫單元測試會用到它。

下面我們來寫個HelloWorld接口,驗證一下項目搭建是否沒問題。

代碼如下:

package com.dgd.multidatasource.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 14:17
 * @description : HelloWorld 控制器
 */
@RestController
public class HelloWorldController
{
    @GetMapping("/hello/{userName}")
    public String helloWorld(@PathVariable String userName)
    {
        return "Hello:" + userName;
    }
}

新建包并取命為:com.dgd.multidatasource.controller;新建類并取名為:HelloWorldController,在類上添加注解@RestController,該注解將幫助我們創(chuàng)建REST風格的web服務,具體講解參看此;寫一個方法名為:helloWorld,方法上添加注解GetMapping,表明該方法只接收GET請求,入?yún)⑸咸砑幼⒔?code>@PathVariable,它將幫我們讀取到請求路徑上定義的userName參數(shù)。此時我們的項目如下圖示:

Hello World

接下來我們把項目啟動,回到MultiDatasourceApplication類,點擊綠色小圖標,選擇Run選項,啟動項目,如圖示:

啟動項目1

啟動項目2

看到控制臺輸出如下日志,表明項目啟動沒問題:

啟動項目3

接著,我們在瀏覽器地址欄上輸入http://localhost:8080/hello/Dannis,看到網(wǎng)頁上出現(xiàn)Hello:Dannis,表明SpringBoot項目成功搭建完成。

數(shù)據(jù)初始化

現(xiàn)在我們來創(chuàng)建兩個數(shù)據(jù)源,真實場景的多數(shù)據(jù)源,數(shù)據(jù)庫所在的服務器一般是不相同的,如果是為了模擬真實環(huán)境,我們可以在自己電腦上搭建兩個虛擬機,分別搭建數(shù)據(jù)庫,或者利用Docker來創(chuàng)建兩個數(shù)據(jù)庫,或者買兩個云服務器,分別在上面搭建兩個數(shù)據(jù)庫,為了簡單起見,也可以是在同一個MySql服務上創(chuàng)建兩個不同的庫,我們就按最后一種情況來,假設已在本地上安裝好MySql服務環(huán)境,接下來,我們用下面的腳本命令來初始化我們的測試數(shù)據(jù):

# 創(chuàng)建第一個數(shù)據(jù)源
DROP DATABASE IF EXISTS `ds_01`;
CREATE DATABASE `ds_01`;

# 創(chuàng)建用戶表并初始化數(shù)據(jù)
DROP TABLE IF EXISTS `ds_01`.`user`;
CREATE TABLE `ds_01`.`user` (
`id` BIGINT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '用戶ID',
`user_name` VARCHAR(16) NOT NULL COMMENT '用戶名'
);
INSERT INTO `ds_01`.`user` (`user_name`) VALUES
('Dannis'),
('小飛飛');

# 創(chuàng)建第二個數(shù)據(jù)源
DROP DATABASE IF EXISTS `ds_02`;
CREATE DATABASE `ds_02`;

# 創(chuàng)建訂單表并初始化數(shù)據(jù)
DROP TABLE IF EXISTS `ds_02`.`order`;
CREATE TABLE `ds_02`.`order` (
`id` BIGINT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '訂單ID',
`user_id` BIGINT(11) NOT NULL COMMENT '用戶ID',
`address` VARCHAR(32) NOT NULL COMMENT '收貨地址'
);
INSERT INTO `ds_02`.`order` (`user_id`,`address`) VALUES
(1,'北京市朝陽區(qū)'),
(2,'廣州市海珠區(qū)');

SQL腳本執(zhí)行完畢,點擊localhost鼠標右鍵選擇刷新,然后可看到出現(xiàn)兩個數(shù)據(jù)庫ds_01ds_02,打開查看一下,發(fā)現(xiàn)數(shù)據(jù)已正常寫入,如下圖所示:

初始化數(shù)據(jù)

利用Mybatis Plus來訪問數(shù)據(jù)

Mybatis Plus是ORM框架MyBatis的增強版,具體介紹可查看官網(wǎng)

這里我們選用它來簡化對數(shù)據(jù)庫的操作,同時,我們也引入Lombok插件來簡化Java對象相關方法的編碼(IDEA需提前安裝好Lombok插件并添加相關配置,具體步驟可自行百度),在pom.xml添加如下代碼:

配置版本號:

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <springboot.version>2.2.8.RELEASE</springboot.version>
        <lombok.version>1.18.4</lombok.version>
        <mysql-connector-java.version>5.1.42</mysql-connector-java.version>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
    </properties>

引入依賴:

  <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector-java.version}</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <!-- lombok 依賴 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>

新增包并命名為com.dgd.multidatasource.model.mybatis.entity,

新建User類,代碼如下:

package com.dgd.multidatasource.model.mybatis.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 15:33
 * @description : 用戶表
 */
@Data
@TableName("`user`")
public class User implements Serializable
{
    private Long id;
    
    private String userName;
}

新建Order類,代碼如下:

package com.dgd.multidatasource.model.mybatis.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 15:35
 * @description : 訂單表
 */
@Data
@TableName("`order`")
public class Order implements Serializable
{
    private Long id;

    private Long userId;

    private String address;
}

新增包并命名為com.dgd.multidatasource.model.mybatis.mapper,

新建UserMapper類,代碼如下:

package com.dgd.multidatasource.model.mybatis.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dgd.multidatasource.model.mybatis.entity.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 15:42
 * @description : 用戶表映射接口
 */
@Mapper
public interface UserMapper extends BaseMapper<User>
{
}

新建OrderMapper類,代碼如下:

package com.dgd.multidatasource.model.mybatis.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dgd.multidatasource.model.mybatis.entity.Order;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 15:43
 * @description : 訂單表映射接口
 */
@Mapper
public interface OrderMapper extends BaseMapper<Order>
{
}

在配置類application.yml上添加如下配置:

# DataSource Config
spring:
  datasource:
    # 指定驅(qū)動類
    driver-class-name: com.mysql.jdbc.Driver
    # 數(shù)據(jù)庫地址
    url: jdbc:mysql://localhost:3306/ds_01?serverTimezone=Asia/Shanghai&useSSL=false
    # 數(shù)據(jù)庫用戶名
    username: root
    # 數(shù)據(jù)庫用戶密碼
    password: root

MultiDatasourceApplication類上指定Mapper掃描路徑,如下:

@MapperScan("com.dgd.multidatasource.model.mybatis.mapper")

寫個單元測試來驗證下MyBatis Plus是否能正常訪問ds_01上的數(shù)據(jù),代碼如下:

package com.dgd.multidatasource.model.mybatis;

import com.dgd.multidatasource.model.mybatis.entity.User;
import com.dgd.multidatasource.model.mybatis.mapper.UserMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 15:39
 * @description : MybatisPlus 功能測試
 */
@SpringBootTest
public class MybatisPlusTest
{
    @Autowired
    UserMapper userMapper;
    @Test
    void userTest()
    {
        User user = userMapper.selectById(2L);
        Assertions.assertNotNull(user);
        Assertions.assertEquals("小飛飛", user.getUserName(), "用戶名不正確");
        System.out.println("查詢結(jié)果:" + user);
    }
}

運行測試用例:

測試用例

控制臺輸出如下結(jié)果,表明Mybatis Plus已能正常使用。
測試用例成功通過

利用ShardingSphere實現(xiàn)多數(shù)據(jù)源切換

上面我們通過Mybatis Plus已能正常訪問ds_01上的數(shù)據(jù),但是如果想要同時訪問ds_02上的訂單數(shù)據(jù),就要借助ShardingSphere中間件了,下面來引入相關依賴,如下:

指定版本號:

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <springboot.version>2.2.8.RELEASE</springboot.version>
        <lombok.version>1.18.4</lombok.version>
        <mysql-connector-java.version>5.1.42</mysql-connector-java.version>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
        <sharding-sphere.version>4.0.0-RC2</sharding-sphere.version>
   </properties>

引入依賴:

 <!-- shardingSphere 依賴 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>${sharding-sphere.version}</version>
        </dependency>

接著我們把application.yml文件里內(nèi)容改成如下所示:

spring:
    shardingsphere:
        props:
            sql:
                show:
                    true
        datasource:
            names: ds1,ds2
            ds1:
                type: com.zaxxer.hikari.HikariDataSource
                driverClassName: com.mysql.jdbc.Driver
                jdbc-url: jdbc:mysql://localhost:3306/ds_01?serverTimezone=Asia/Shanghai&useSSL=false
                username: root
                password: root
            ds2:
                type: com.zaxxer.hikari.HikariDataSource
                driverClassName: com.mysql.jdbc.Driver
                jdbc-url: jdbc:mysql://localhost:3306/ds_02?serverTimezone=Asia/Shanghai&useSSL=false
                username: root
                password: root
        sharding:
            defaultDatabaseStrategy:
                hint:
                    algorithmClassName: com.dgd.multidatasource.shardingsphere.MyDatasourceRoutingAlgorithm
            tables:
                user:
                    actualDataNodes: ds1.user
                order:
                    actualDataNodes: ds2.order
            defaultTableStrategy:
                none:
                    any: ""      
        

我們對上面用到的參數(shù)做下說明:
spring:shardingsphere:props:sql:show:是否開啟SQL顯示,默認是false,開發(fā)過程我們把它設成true以方便查看SQL執(zhí)行過程。
spring:shardingsphere:datasource:names:指定數(shù)據(jù)源名字,多個數(shù)據(jù)源之間以逗號分隔,下面就是對聲明的數(shù)據(jù)源ds1ds2進行相關屬性配置,不再贅述。
spring:shardingsphere:sharding:defaultDatabaseStrategy:hint:algorithmClassName:聲明默認數(shù)據(jù)庫分片策略使用Hint策略,指定Hint分片算法類名稱,該類需實現(xiàn)HintShardingAlgorithm接口并提供無參數(shù)的構造器。
spring:shardingsphere:sharding:tables:數(shù)據(jù)分片規(guī)則配置,user,order是我們聲明的邏輯表名稱,actualDataNodes指定實際的數(shù)據(jù)節(jié)點,由數(shù)據(jù)源名 + 邏輯表名組成,以小數(shù)點分隔。
spring:shardingsphere:sharding:defaultTableStrategy:none:因為我們只是用到分庫功能,并不需要進行分表,因此,指定默認的分表策略為noneany是我們給該策略取的名字,可以為任意字符串,其值為空。

更多參數(shù)配置項說明可參看官網(wǎng)。

從上面的配置內(nèi)容可知,除了要配置數(shù)據(jù)源外,還有配置分片策略,由于我們希望的是想讓它訪問哪個數(shù)據(jù)源就訪問哪個數(shù)據(jù)源,即強制路由,而ShardingSphereHint分片策略正好可以滿足我們的這個需求。

以下關于Hint的簡單介紹摘自官網(wǎng)。

ShardingSphere使用ThreadLocal管理分片鍵值進行Hint強制路由。可以通過編程的方式向HintManager中添加分片值,該分片值僅在當前線程內(nèi)生效。

Hint方式主要使用場景:

  • 分片字段不存在SQL中、數(shù)據(jù)庫表結(jié)構中,而存在于外部業(yè)務邏輯。
  • 強制在主庫進行某些數(shù)據(jù)操作。

更多分片策略可參考ShardingSphere官網(wǎng)

下面我們來開始寫分片策略的實現(xiàn)類,首先定義兩個數(shù)據(jù)源常量,如下:

package com.dgd.multidatasource.shardingsphere;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 16:46
 * @description : 數(shù)據(jù)源枚舉
 */
public enum DatasourceType
{
    /**
     * 用戶數(shù)據(jù)源
     */
    DATASOURCE_USER,
    /**
     * 訂單數(shù)據(jù)源
     */
    DATASOURCE_ORDER
}

數(shù)據(jù)庫分片策略代碼實現(xiàn):

package com.dgd.multidatasource.shardingsphere;

import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashSet;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 16:42
 * @description : 數(shù)據(jù)庫分片策略
 */
public class MyDatasourceRoutingAlgorithm implements HintShardingAlgorithm<String>
{
    private static final Logger LOGGER = LoggerFactory.getLogger(MyDatasourceRoutingAlgorithm.class);

    /**
     * 用戶數(shù)據(jù)源
     */
    private static final String DS_USER = "ds1";

    /**
     * 訂單數(shù)據(jù)源
     */
    private static final String DS_ORDER = "ds2";

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<String> shardingValue)
    {
        Collection<String> result = new HashSet<>();
        for(String value : shardingValue.getValues())
        {
            if(DatasourceType.DATASOURCE_USER.toString().equals(value))
            {
                if(availableTargetNames.contains(DS_USER))
                {
                    result.add(DS_USER);
                }
            }
            else
            {
                if(availableTargetNames.contains(DS_ORDER))
                {
                    result.add(DS_ORDER);
                }
            }
        }
        LOGGER.info("availableTargetNames:{},shardingValue:{},返回的數(shù)據(jù)源:{}",
                new Object[] { availableTargetNames, shardingValue, result });

        return result;
    }
}

好了,寫個測試用例測試一下,新建包名為com.dgd.multidatasource.shardingsphere,測試類名為DatasourceRoutingTest,具體測試代碼如下:

package com.dgd.multidatasource.shardingsphere;

import com.dgd.multidatasource.model.mybatis.entity.Order;
import com.dgd.multidatasource.model.mybatis.entity.User;
import com.dgd.multidatasource.model.mybatis.mapper.OrderMapper;
import com.dgd.multidatasource.model.mybatis.mapper.UserMapper;
import org.apache.shardingsphere.api.hint.HintManager;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 17:05
 * @description : 數(shù)據(jù)源切換功能驗證
 */
@SpringBootTest
public class DatasourceRoutingTest
{
    @Autowired
    UserMapper userMapper;
    
    @Autowired
    OrderMapper orderMapper;

    @Test
    void test()
    {
        HintManager hintManager = HintManager.getInstance();
        // 分庫不分表情況下,強制路由至某一個分庫時,可使用hintManager.setDatabaseShardingValue方式添加分片
        // 通過此方式添加分片鍵值后,將跳過SQL解析和改寫階段,從而提高整體執(zhí)行效率。
        // 詳情參考:
        // https://shardingsphere.apache.org/document/legacy/4.x/document/cn/manual/sharding-jdbc/usage/hint/
        hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_USER.toString());
        // 訪問用戶數(shù)據(jù)源
        User user = userMapper.selectById(2L);
        Assertions.assertNotNull(user);
        Assertions.assertEquals("小飛飛", user.getUserName(), "用戶名不正確");
        System.out.println("用戶查詢結(jié)果:" + user);
        hintManager.close();

        hintManager.setDatabaseShardingValue(DatasourceType.DATASOURCE_ORDER.toString());
        // 訪問訂單數(shù)據(jù)源
        Order order = orderMapper.selectById(1L);
        Assertions.assertNotNull(order);
        Assertions.assertEquals("北京市朝陽區(qū)", order.getAddress(), "地址不正確");
        System.out.println("訂單查詢結(jié)果:" + order);
        hintManager.close();
    }
}

測試結(jié)果顯示如下圖所示,說明數(shù)據(jù)源已能成功切換:

數(shù)據(jù)源切換成功測試用例

最后,為了能在web端訪問我們的項目,加上Controller等相關代碼,具體代碼如下:

創(chuàng)建com.dgd.multidatasource.service包,新建兩個類,分別為UserService,OrderService,代碼分別為:

package com.dgd.multidatasource.service;

import com.dgd.multidatasource.model.mybatis.entity.User;
import com.dgd.multidatasource.model.mybatis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 19:14
 * @description : 用戶服務方法
 */
@Service
public class UserService
{
    @Autowired
    private UserMapper userMapper;

    public User queryById(long id)
    {
        return userMapper.selectById(id);
    }
}
package com.dgd.multidatasource.service;

import com.dgd.multidatasource.model.mybatis.entity.Order;
import com.dgd.multidatasource.model.mybatis.mapper.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 19:15
 * @description : 訂單服務方法
 */
@Service
public class OrderService
{
    @Autowired
    private OrderMapper orderMapper;

    public Order queryById(long id)
    {
        return orderMapper.selectById(id);
    }
}

在原來的controller包下添加一個類,名為BusinessController,代碼如下:

package com.dgd.multidatasource.controller;

import com.dgd.multidatasource.model.mybatis.entity.Order;
import com.dgd.multidatasource.model.mybatis.entity.User;
import com.dgd.multidatasource.service.OrderService;
import com.dgd.multidatasource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author : DaiGD
 * @createtime :  2020年06月13日 19:17
 * @description : 業(yè)務功能控制器
 */
@RestController
public class BusinessController
{
    @Autowired
    private UserService userService;

    @Autowired
    private OrderService orderService;

    @GetMapping("/user/{id}")
    public User queryByUserId(@PathVariable Long id)
    {
        return userService.queryById(id);
    }

    @GetMapping("/order/{id}")
    public Order queryByOrderId(@PathVariable Long id)
    {
        return orderService.queryById(id);
    }
}

之后啟動項目,在瀏覽上分別輸入:http://localhost:8080/user/1http://localhost:8080/order/2,可以看到瀏覽器分別響應:

{"id":1,"userName":"Dannis"}
{"id":2,"userId":2,"address":"廣州市海珠區(qū)"}

說明數(shù)據(jù)源切換在web層也正常。

防坑記錄

  • 對于分表策略,如果聲明類型為none,如果不指定指定策略的名稱和值,如下所示:

    分表策略未指定
    啟動測試用例會提示如下異常:
    分表異常
    解決方法:
    any:""的注釋去掉即可。
    參考。

  • 因為我們的訂單表名聲明為了order,如果在Order類上的@TableName直接寫成如下所示(注意,order沒有加上反引號):

@Data
@TableName("order")
public class Order implements Serializable
{
    private Long id;

    private Long userId;

    private String address;
}

啟動測試用例會提示如下異常:

表聲明異常
顯然,SQL語句解析時出現(xiàn)了錯誤,它把我們的order當成了MySql內(nèi)置關鍵字了,加上反引號區(qū)分開來即可,如下:

@Data
@TableName("`order`")
public class Order implements Serializable
{
    private Long id;

    private Long userId;

    private String address;
}

項目完整代碼地址

項目完整代碼:
碼云,GitHub。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容