ShardingSphere系列03:ShardingJdbc+MybatisPlus实现多数据源

Mybatisplus+多数据源

整合步骤
基础数据准备
  • 创建表order_info,同时创建同样数据结构的order_info_0,order_info_1,order_info_2,order_info_3
CREATE TABLE `order_info` (
  `id` bigint NOT NULL COMMENT 'id',
  `name` varchar(32) DEFAULT NULL COMMENT '名称',
  `num` int DEFAULT NULL COMMENT '数量',
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

这里的分表逻辑是根据id取余,分成4个表。

1、需要依赖
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--导入mybatisplus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

<!--        shardingjdbc-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.1.2</version>
        </dependency>

<!--        druid数据源,需要导入,否则shardingjdbc无法找到druid数据源会报错-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.9</version>
        </dependency>

<!-- mybatisplus 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
2、基础类准备
package com.walker.mbpsharding.entity;

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

import java.util.Date;

/**
 * @Author: WalkerShen
 * @DATE: 2022/3/29
 * @Description:
 **/
@Data
//使用tableName代表映射的mysql的表
@TableName("order_info")
public class OrderInfo {
    private Long id;
    private String name;
    private Integer num;
    private Date createTime;
}


package com.walker.mbpsharding.mapper;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.walker.mbpsharding.entity.OrderInfo;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * @Author: WalkerShen
 * @DATE: 2022/3/29
 * @Description: 创建mapper接口,
 **/

//使用@Mapper,注入容器
@Mapper
//继承BaseMapper类,可以获取BaseMapper中的方法
public interface OrderInfoMapper extends BaseMapper<OrderInfo> {
    
}

package com.walker.mbpsharding.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.walker.mbpsharding.entity.OrderInfo;

import java.util.List;

public interface OrderInfoService extends IService<OrderInfo> {

    List<OrderInfo> listSharding();
}
package com.walker.mbpsharding.service;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.walker.mbpsharding.entity.OrderInfo;
import com.walker.mbpsharding.mapper.OrderInfoMapper;
import org.springframework.stereotype.Service;

import java.util.List;

//1、使用@Service注入容器
@Service
//2、继承serviceImpl
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService{


    // 使用@DS指定需要执行的数据源
    @DS(value="sharding")
    @Override
    public List<OrderInfo> listSharding() {
        return list();
    }
}

  • 这里对listSharding方法使用了@DS注解,让其使用sharding数据源去执行sql

OrderInfoMapper.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">
<!--namespace:命名空间,用来映射对应的mapper
相当于将mapper和mapper.xml连接起来,这一步很重要-->
<mapper namespace="com.walker.mbpsharding.mapper.OrderInfoMapper">

</mapper>

image.png
注意:xml文件的位置需要和配置文件配置的一样,否则找不到就会报Mapper的Bean找不到的错误

3、动态数据源配置类编写
package com.walker.mbpsharding.config;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import org.apache.shardingsphere.driver.jdbc.adapter.AbstractDataSourceAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;

/**
 * 动态数据源配置:
 *
 * 使用{@link com.baomidou.dynamic.datasource.annotation.DS}注解,切换数据源
 *
 */
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class,
        SpringBootConfiguration.class})
public class DataSourceConfiguration {
    // 分表数据源名称
    private static final String SHARDING_DATA_SOURCE_NAME = "sharding";

    //mybatisplus 动态数据源配置项
    @Autowired
    private DynamicDataSourceProperties properties;

    // shardingjdbc的数据源
    @Lazy
    @Resource(name = "shardingSphereDataSource")
    AbstractDataSourceAdapter shardingSphereDataSource;


    // 动态数据源提供者bean注册
    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        // 首先从mybatisplus的动态数据源先获取
        Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
                // 然后将 shardingjdbc 管理的数据源也交给动态数据源管理
                dataSourceMap.put(SHARDING_DATA_SOURCE_NAME, shardingSphereDataSource);
                return dataSourceMap;
            }
        };
    }



    // 数据源配置 @Primary 代表优先使用该bean 
    @Primary
    @Bean
    public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
//        首选数据源
        dataSource.setPrimary(properties.getPrimary());
        dataSource.setStrict(properties.getStrict());
        dataSource.setStrategy(properties.getStrategy());
//        配置数据源提供者
        dataSource.setProvider(dynamicDataSourceProvider);
        dataSource.setP6spy(properties.getP6spy());
        dataSource.setSeata(properties.getSeata());
        return dataSource;
    }
}

其实就是分别获取mybatisplus的数据源和sharding的数据源,然后将sharding的数据源加入到mybatisplus的动态数据源Map中,然后就可以使用@DS注解去指定数据源了

4、application.yaml配置

spring:
  autoconfigure: # 排除druid 否则报错
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
#  注意格式一定要配好,这里有一个datasource 然后再dynamic,后面再来了一个datasource 才到了配置数据源
  datasource:
  
  # 1、mybatisplus动态数据源的配置
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/table_sharding?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimeZone=UTC
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver

  shardingsphere:
    # 开启sql打印
    enabled: true
    props:
      # 是否显示sql
      sql-show: true
 # 2、shardingjdbc的数据源的配置
    datasource:
      #      数据源名称
      names: sharding
      #      数据源实例: 如果这里还有master
      sharding:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class: com.mysql.cj.jdbc.Driver
        #        使用Druid,不能使用jdbc-url 得使用url
        url: jdbc:mysql://localhost:3306/table_sharding?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
    # 分片规则
    rules:
      sharding:
        #        对表进行分片
        tables:
          #          逻辑表名,代表的是需要分表的名称
          order_info:
            #            实际节点:这里代表的是 会使用sharding数据源中 order_info表 细分为0~3 4个表
            actual-data-nodes: sharding.order_info_$->{0..3}
            #            表策略
            table-strategy:
              #              标准表策略
              standard:
                #                分表的列
                sharding-column: id
                #                分片算法名称: 来源于下面的sharding-algorithms
                sharding-algorithm-name: alg_hash_mod
            key-generate-strategy: # 主键生成策略
              column: id  # 主键列
              key-generator-name: snowflake  # 策略算法名称(推荐使用雪花算法)
        #              主键生成规则,SNOWFLAKE 雪花算法
        key-generators:
          snowflake:
            type: SNOWFLAKE
        #            分片算法
        sharding-algorithms:
          alg_hash_mod:
            #            类型:hash取余  类似于获取一个列的数,假如是3  3%4=0 数据就会进入第0个表
            type: HASH_MOD
            #            分片的数量,因为是4个表,所以是4
            props:
              sharding-count: 4

# mybatisplus配置
mybatis-plus:
  # 配置xml路径
  mapper-locations: classpath*:/mapper/*Mapper.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

5、测试
package com.walker.mbpsharding;

import com.walker.mbpsharding.entity.OrderInfo;
import com.walker.mbpsharding.service.OrderInfoService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@Slf4j
@SpringBootTest
class MybatisplusShardingApplicationTests {

    @Autowired
    private OrderInfoService orderInfoService;


    @Test
    public void list(){
        List<OrderInfo> list = orderInfoService.list();
        log.info("返回结果:{}",list);
    }

    @Test
    public void sharding(){
        List<OrderInfo> list = orderInfoService.listSharding();
        log.info("返回结果:{}",list);
    }

}

执行list方法:
image.png

执行sharding方法
image.png
可以看到,使用分表的原则去查询数据

SELECT  id,name,num,create_time  FROM order_info_0 UNION ALL SELECT  id,name,num,create_time  FROM order_info_1 UNION ALL SELECT  id,name,num,create_time  FROM order_info_2 UNION ALL SELECT  id,name,num,create_time  FROM order_info_3
疑问
如果需要配置druid数据源的话,需要如何配置呢?

我们可以查看DynamicDataSourceProperties类,可以看到关于Druid的配置
image.png

所以我们要如此配置:
放在指定的数据源下面: druid.xxx
image.png

spring:
#  注意格式一定要配好,这里有一个datasource 然后再dynamic,后面再来了一个datasource 才到了配置数据源
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/table_sharding?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimeZone=UTC
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          druid:
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            wall:
              multi-statement-allow: true
              condition-and-alway-true-allow: true
            stat:
              # 慢SQL记录
              logSlowSql: true
              slowSqlMillis: 1000
              mergeSql: true
参考文档

mybatisplus多数据源配置参考:
https://baomidou.com/pages/a61e1b/

总结:

整合Mybatisplus应该是比较常见的场景了,现在大部分企业都有使用mp。

也可以看看历史文章学习一下哦~
ShardingSphere系列01:Shardingjdbc实现分表(含项目实践)

ShardingSphere系列02:ShardingJdbc+Mybatis实现多数据源

相关推荐

  1. springboot实现数据

    2024-04-06 11:22:01       46 阅读
  2. ShardingSphere5.3.0配置单数据分表

    2024-04-06 11:22:01       29 阅读
  3. Springboot实现配置数据

    2024-04-06 11:22:01       55 阅读
  4. Springboot JPA实现数据配置

    2024-04-06 11:22:01       54 阅读
  5. 若依实现数据

    2024-04-06 11:22:01       42 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-06 11:22:01       91 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-06 11:22:01       97 阅读
  3. 在Django里面运行非项目文件

    2024-04-06 11:22:01       78 阅读
  4. Python语言-面向对象

    2024-04-06 11:22:01       88 阅读

热门阅读

  1. 在Ubuntu 14.04上如何备份和恢复Redis数据

    2024-04-06 11:22:01       33 阅读
  2. Flink集群从节点TaskManager启动分析

    2024-04-06 11:22:01       26 阅读
  3. 大语言模型LLM《提示词工程指南》学习笔记01

    2024-04-06 11:22:01       28 阅读
  4. 如何更改WordPress站点的域名:完全指南

    2024-04-06 11:22:01       35 阅读
  5. Day3-struct类型、列转行、行转列、函数

    2024-04-06 11:22:01       30 阅读
  6. MySQL 里记录货币用什么字段

    2024-04-06 11:22:01       32 阅读
  7. C# Socket发送、接收结构体

    2024-04-06 11:22:01       39 阅读
  8. 【ubuntu】Vim配置记录

    2024-04-06 11:22:01       33 阅读
  9. ubuntu20.04 安裝PX4 1.13

    2024-04-06 11:22:01       36 阅读
  10. 习题3-2 高速公路超速处罚

    2024-04-06 11:22:01       32 阅读