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实现多数据源

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
ShardingSphere中,可以通过配置多个数据源来实现多数据源的支持。同时,为了支持MyBatis的插件,也需要在配置文件中配置相应的插件。 以下是一个示例配置文件,其中包括两个数据源和对应的MyBatis插件配置: ```yaml spring: datasource: # 第一个数据源配置 ds1: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/db1?useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2B8 username: root password: root # 第二个数据源配置 ds2: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/db2?useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2B8 username: root password: root mybatis: mapper-locations: classpath*:mapper/*.xml plugins: # 插件1配置 - plugin: com.example.plugin.Plugin1 properties: property1: value1 # 插件2配置 - plugin: com.example.plugin.Plugin2 properties: property2: value2 ``` 在代码中,可以通过`@MapperScan`注解来指定扫描的Mapper接口所在的包,同时也可以通过`@Qualifier`注解来指定使用哪个数据源,示例代码如下: ```java @SpringBootApplication @MapperScan(basePackages = "com.example.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean(name = "ds1SqlSessionFactory") @Primary public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setDataSource(dataSource); sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath*:mapper/ds1/*.xml")); return sessionFactoryBean.getObject(); } @Bean(name = "ds2SqlSessionFactory") public SqlSessionFactory ds2SqlSessionFactory(@Qualifier("ds2DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setDataSource(dataSource); sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath*:mapper/ds2/*.xml")); return sessionFactoryBean.getObject(); } @Bean(name = "ds1DataSource") @ConfigurationProperties(prefix = "spring.datasource.ds1") @Primary public DataSource ds1DataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "ds2DataSource") @ConfigurationProperties(prefix = "spring.datasource.ds2") public DataSource ds2DataSource() { return DataSourceBuilder.create().build(); } } ``` 在上述代码中,`@Primary`注解用于指定默认数据源,可以通过`@Qualifier`注解指定使用哪个数据源,如: ```java @Autowired @Qualifier("ds1SqlSessionFactory") private SqlSessionFactory ds1SqlSessionFactory; ``` 这样即可在代码中使用对应的数据源和MyBatis插件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WalkerShen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值