多数据源与分库分表

一、自定义多数据源方式

多数据源复制配置类即可。

1.1 Java配置类
package com.xx.wholesale.merchant.config.datasource;


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
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.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.io.FileNotFoundException;

@Configuration
@MapperScan(value = "com.xx.wholesale.merchant" + MerchantDataSourceConfig.DATA_SOURCE_SUB_NAME + ".dao",
        sqlSessionFactoryRef = MerchantDataSourceConfig.DATA_SOURCE_SUB_NAME + "SqlSessionFactory",
        sqlSessionTemplateRef = MerchantDataSourceConfig.DATA_SOURCE_SUB_NAME + "SqlSessionTemplate"
)
public class MerchantDataSourceConfig {

    static final String DATA_SOURCE_SUB_NAME = "merchant";

    @Bean(value = DATA_SOURCE_SUB_NAME + "DataSource")
    @ConfigurationProperties(prefix = "spring.datasource." + DATA_SOURCE_SUB_NAME)
    public HikariDataSource dataSource() {
        return new HikariDataSource();
    }


    @Bean(value = DATA_SOURCE_SUB_NAME + "SqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier(value = DATA_SOURCE_SUB_NAME + "DataSource") DataSource dataSource) throws Exception {
        DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setConfigLocation(resourceLoader.getResource("classpath:mybatis-config.xml"));
        Resource[] resources = null;
        try {
            resources = resolver.getResources("classpath:mapper/" + DATA_SOURCE_SUB_NAME + "/*.xml");
        } catch (FileNotFoundException e) {
            resources = new Resource[0];
        }
        factory.setMapperLocations(resources);
        MybatisPlusInterceptor paginationInterceptor = new MybatisPlusInterceptor();
        paginationInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        factory.setPlugins(paginationInterceptor);
        return factory.getObject();
    }

    @Bean(value = DATA_SOURCE_SUB_NAME + "SqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier(value = DATA_SOURCE_SUB_NAME + "SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
        return sqlSessionTemplate;
    }

    @Bean(value = DATA_SOURCE_SUB_NAME + "TransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier(value = DATA_SOURCE_SUB_NAME + "DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
2.2 配置

application.yml

spring:
  datasource:
    merchant:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://10.30.20.205:6033/le_shou?zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=true&useAffectedRows=true&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      # 连接池最大连接数,默认是10
      maximum-pool-size: 30
      minimum-idle: 2
      max-lifetime: 7200000
      # 空闲连接存活最大时间,默认600000(10分钟)
      idle-timeout: 300000
      validation-timeout: 1000
      # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
      connection-timeout: 3000
      connection-test-query: select 1
      auto-commit: true

二、结合Sharding-JDBC做多数据源

基础描述
  • springboot: 2.7.x
  • shardingsphere-jdbc-core: 5.4.x
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.17</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xx.wholesale.merchant</groupId>
    <artifactId>wholesale-merchant</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>wholesale-merchant</name>
    <description>wholesale-merchant</description>
    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <mysql-connector-java.version>8.0.17</mysql-connector-java.version>
        <mybatis-spring-boot-starter.version>2.3.1</mybatis-spring-boot-starter.version>
        <mybatis-plus-boot-starter.version>3.5.4.1</mybatis-plus-boot-starter.version>
        <shardingsphere-jdbc-core.version>5.4.1</shardingsphere-jdbc-core.version>
        <snakeyaml.version>1.33</snakeyaml.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>*</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core</artifactId>
            <version>${shardingsphere-jdbc-core.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

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

        <!-- MySQL Connector/J -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector-java.version}</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis-spring-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
application.yml相关配置
server:
  port: 8899
  tomcat:
    basedir: ./
    uri-encoding: UTF-8
    max-threads: 1000
    min-spare-threads: 30
    accesslog:
      enabled: true
      directory: ${logging.file.path}
      pattern: "%h %l %u %t %r %s %b %D"

spring:
  application:
    name: wholesale-merchant
  profiles:
    include: jdbc

logging:
  config: classpath:log4j2_config.xml
  file:
    name: ${spring.application.name}
    path: logs

mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      table-underline: true

application-jdbc.yml配置

spring:
  datasource:
    bdata:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://127.0.0.1:3306/bus_data?zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      # 连接池最大连接数,默认是10
      maximum-pool-size: 30
      minimum-idle: 2
      max-lifetime: 7200000
      # 空闲连接存活最大时间,默认600000(10分钟)
      idle-timeout: 300000
      validation-timeout: 1000
      # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
      connection-timeout: 3000
      connection-test-query: select 1
      auto-commit: true
  shardingsphere:
    busorder:
      mode:
        type: standalone
        repository:
          type: JDBC
      data-sources:
        bus_order_0:
          driver-class-name: com.mysql.cj.jdbc.Driver
          # 此配置使用YamlDataSourceConfigurationSwapper.swapToDataSources()生成Map<String,DataSource>使用
          # dataSourceClassName: com.zaxxer.hikari.HikariDataSource
          jdbc-url: jdbc:mysql://127.0.0.1:3306/bus_order_0?zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
          # 连接池最大连接数,默认是10
          maximum-pool-size: 30
          minimum-idle: 2
          max-lifetime: 7200000
          # 空闲连接存活最大时间,默认600000(10分钟)
          idle-timeout: 300000
          validation-timeout: 1000
          # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
          connection-timeout: 3000
          connection-test-query: select 1
          auto-commit: true
        bus_order_1:
          driver-class-name: com.mysql.cj.jdbc.Driver
          # dataSourceClassName: com.zaxxer.hikari.HikariDataSource
          jdbc-url: jdbc:mysql://127.0.0.1:3306/bus_order_1?zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
          # 连接池最大连接数,默认是10
          maximum-pool-size: 30
          minimum-idle: 2
          max-lifetime: 7200000
          # 空闲连接存活最大时间,默认600000(10分钟)
          idle-timeout: 300000
          validation-timeout: 1000
          # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
          connection-timeout: 3000
          connection-test-query: select 1
          auto-commit: true
      rules:
#        - type: org.apache.shardingsphere.sharding.yaml.config.YamlShardingRuleConfiguration
        sharding:
          key-generators:
            snowflake:
              type: SNOWFLAKE
          sharding-algorithms:
            db_choose_bus_order_algorithm:
              type: INLINE
              props:
                algorithm-expression: bus_order_${user_id % 2}
            db_choose_account_algorithm:
              type: INLINE
              props:
                algorithm-expression: bus_order_${user_id % 2}
            tb_order_algorithm:
              type: ORDER_ALGORITHM
#              type: INLINE
#              props:
#                algorithm-expression: t_order_${order_id % 2}
          default-database-strategy:
            standard:
              # 分片列名称
              sharding-column: user_id
              # 分片算法名称
              sharding-algorithm-name: db_choose_bus_order_algorithm
          tables:
            t_order:
              actual-data-nodes: bus_order_${0..1}.t_order_${0..1}
              tableStrategy:
                standard:
                  shardingColumn: order_id
                  shardingAlgorithmName: tb_order_algorithm
            t_account:
              actual-data-nodes: bus_order_${0..1}.t_account
              databaseStrategy:
                shardingColumn: user_id
                shardingAlgorithmName: db_choose_account_algorithm
      # 展示修改以后的sql语句
      props:
        sql-show: true
DataSource相关配置
  • BusDataDataSourceConfig.java
package com.xx.wholesale.merchant.config.datasource;


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
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.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.io.FileNotFoundException;

@Configuration
@MapperScan(value = "com.xx.wholesale.merchant." + BusDataDataSourceConfig.DATA_SOURCE_SUB_NAME + ".dao",
        sqlSessionFactoryRef = BusDataDataSourceConfig.DATA_SOURCE_SUB_NAME + "SqlSessionFactory",
        sqlSessionTemplateRef = BusDataDataSourceConfig.DATA_SOURCE_SUB_NAME + "SqlSessionTemplate"
)
public class BusDataDataSourceConfig {

    static final String DATA_SOURCE_SUB_NAME = "busdata";

    @Bean(value = DATA_SOURCE_SUB_NAME + "DataSource")
    @ConfigurationProperties(prefix = "spring.datasource." + DATA_SOURCE_SUB_NAME)
    public HikariDataSource dataSource() {
        return new HikariDataSource();
    }


    @Bean(value = DATA_SOURCE_SUB_NAME + "SqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier(value = DATA_SOURCE_SUB_NAME + "DataSource") DataSource dataSource) throws Exception {
        DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setConfigLocation(resourceLoader.getResource("classpath:mybatis-config.xml"));
        Resource[] resources = null;
        try {
            resources = resolver.getResources("classpath:mapper/" + DATA_SOURCE_SUB_NAME + "/*.xml");
        } catch (FileNotFoundException e) {
            resources = new Resource[0];
        }
        factory.setMapperLocations(resources);
        MybatisPlusInterceptor paginationInterceptor = new MybatisPlusInterceptor();
        paginationInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        factory.setPlugins(paginationInterceptor);
        return factory.getObject();
    }

    @Bean(value = DATA_SOURCE_SUB_NAME + "SqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier(value = DATA_SOURCE_SUB_NAME + "SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
        return sqlSessionTemplate;
    }

    @Bean(value = DATA_SOURCE_SUB_NAME + "TransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier(value = DATA_SOURCE_SUB_NAME + "DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
  • BusOrderNodeDataSourceConfig.java
package com.xx.wholesale.merchant.config.datasource;


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.driver.api.yaml.YamlJDBCConfiguration;
import org.apache.shardingsphere.driver.api.yaml.YamlShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.yaml.config.swapper.resource.YamlDataSourceConfigurationSwapper;
import org.apache.shardingsphere.sharding.yaml.config.YamlShardingRuleConfiguration;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.io.FileNotFoundException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@MapperScan(value = "com.xx.wholesale.merchant." + BusOrderNodeDataSourceConfig.DATA_SOURCE_SUB_NAME + ".dao",
        sqlSessionFactoryRef = BusOrderNodeDataSourceConfig.DATA_SOURCE_SUB_NAME + "SqlSessionFactory",
        sqlSessionTemplateRef = BusOrderNodeDataSourceConfig.DATA_SOURCE_SUB_NAME + "SqlSessionTemplate"
)
public class BusOrderNodeDataSourceConfig {

    static final String DATA_SOURCE_SUB_NAME = "busorder";


    @ConfigurationProperties(prefix = "spring.shardingsphere." + DATA_SOURCE_SUB_NAME + ".rules.sharding")
    @Bean(value = DATA_SOURCE_SUB_NAME + "YamlShardingRuleConfiguration")
    public YamlShardingRuleConfiguration yamlShardingRuleConfiguration() {
        return new YamlShardingRuleConfiguration();
    }

    @ConfigurationProperties(prefix = "spring.shardingsphere." + DATA_SOURCE_SUB_NAME)
    @Bean(value = DATA_SOURCE_SUB_NAME + "YamlJDBCConfiguration")
    public YamlJDBCConfiguration yamlJDBCConfiguration(@Qualifier(value = DATA_SOURCE_SUB_NAME + "YamlShardingRuleConfiguration") YamlShardingRuleConfiguration yamlShardingRuleConfiguration) {
        YamlJDBCConfiguration yamlJDBCConfiguration = new YamlJDBCConfiguration();
        yamlJDBCConfiguration.getRules().add(yamlShardingRuleConfiguration);
        return yamlJDBCConfiguration;
    }

    @ConfigurationProperties(prefix = "spring.shardingsphere." + DATA_SOURCE_SUB_NAME + ".data-sources")
    @Bean(value = DATA_SOURCE_SUB_NAME + "HikariDataSourceMap")
    public Map<String, HikariDataSource> dataSourcesMap() {
        return new LinkedHashMap<>();
    }

    @Bean(value = DATA_SOURCE_SUB_NAME + "DataSource")
    public DataSource dataSource(@Qualifier(value = DATA_SOURCE_SUB_NAME + "HikariDataSourceMap") Map<String, HikariDataSource> dataSourcesMap
            ,@Qualifier( DATA_SOURCE_SUB_NAME + "YamlJDBCConfiguration") YamlJDBCConfiguration yamlJDBCConfiguration) throws Exception {
        Class<YamlShardingSphereDataSourceFactory> calzz = YamlShardingSphereDataSourceFactory.class;
        Field field = calzz.getDeclaredField("DATA_SOURCE_SWAPPER");
        Method method = calzz.getDeclaredMethod("createDataSource", Map.class, YamlJDBCConfiguration.class);
        field.setAccessible(true);
        method.setAccessible(true);
        YamlDataSourceConfigurationSwapper dataSourceConfigurationSwapper = (YamlDataSourceConfigurationSwapper) field.get(null);
        // 如用官方生成DataSource,需注意类HikariDataSourcePoolMetaData中配置映射和StorageResourceUtils,特别是url和jdbcUrl
        //return (DataSource) method.invoke(null, dataSourceConfigurationSwapper.swapToDataSources(yamlJDBCConfiguration.getDataSources()), yamlJDBCConfiguration);
        return (DataSource) method.invoke(null, dataSourcesMap, yamlJDBCConfiguration);
    }


    @Bean(value = DATA_SOURCE_SUB_NAME + "SqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier(value = DATA_SOURCE_SUB_NAME + "DataSource") DataSource dataSource) throws Exception {
        DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setConfigLocation(resourceLoader.getResource("classpath:mybatis-config.xml"));
        Resource[] resources = null;
        try {
            resources = resolver.getResources("classpath:mapper/" + DATA_SOURCE_SUB_NAME + "/*.xml");
        } catch (FileNotFoundException e) {
            resources = new Resource[0];
        }
        factory.setMapperLocations(resources);
        MybatisPlusInterceptor paginationInterceptor = new MybatisPlusInterceptor();
        paginationInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        factory.setPlugins(paginationInterceptor);
        return factory.getObject();
    }

    @Bean(value = DATA_SOURCE_SUB_NAME + "SqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier(value = DATA_SOURCE_SUB_NAME + "SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
        return sqlSessionTemplate;
    }

    @Bean(value = DATA_SOURCE_SUB_NAME + "TransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier(value = DATA_SOURCE_SUB_NAME + "DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}
  • OrderShardingAlgorithm.java
package com.xx.wholesale.merchant.config.util;

import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

import java.util.Collection;

/**
 * 自定义订单分表策略实现
 */
public class OrderShardingAlgorithm implements StandardShardingAlgorithm<String> {
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {
        return "t_order_" + Long.valueOf(preciseShardingValue.getValue()) % 2;
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<String> rangeShardingValue) {
        return null;
    }

    @Override
    public String getType() {
        return "ORDER_ALGORITHM";
    }
}
  • SPI配置
    src/main/resources/下创建文件夹META-INF/services,并创建文org.apache.shardingsphere.sharding.spi.ShardingAlgorithm,内容如下:
com.xx.wholesale.merchant.config.util.OrderShardingAlgorithm
示例
  • 数据库
CREATE DATABASE bus_data CHARACTER SET = utf8;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `user_id` bigint(20) NOT NULL,
  `user_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `t_user` VALUES (1, 'jon', '2023-11-25 19:59:55');
INSERT INTO `t_user` VALUES (2, '第三眼的思绪', '2023-11-25 20:12:32');


CREATE DATABASE bus_order_0 CHARACTER SET = utf8;
DROP TABLE IF EXISTS `t_account`;
CREATE TABLE `t_account`  (
  `user_id` bigint(20) NOT NULL,
  `amount` bigint(20) NOT NULL DEFAULT 0 COMMENT '账户余额',
  `consume_amount` bigint(20) NOT NULL COMMENT '消费金额',
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户账户表' ROW_FORMAT = Dynamic;

INSERT INTO `t_account` VALUES (1, 10, 20, '2023-11-25 20:16:17');

DROP TABLE IF EXISTS `t_order_0`;
CREATE TABLE `t_order_0`  (
  `order_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_id` bigint(20) NOT NULL,
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `t_order_0` VALUES ('002000', 2, '2023-11-25 20:08:00');

DROP TABLE IF EXISTS `t_order_1`;
CREATE TABLE `t_order_1`  (
  `order_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_id` bigint(20) NOT NULL,
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `t_order_1` VALUES ('002001', 2, '2023-11-25 20:09:18');


CREATE DATABASE bus_order_1 CHARACTER SET = utf8;
DROP TABLE IF EXISTS `t_account`;
CREATE TABLE `t_account`  (
  `user_id` bigint(20) NOT NULL,
  `amount` bigint(20) NOT NULL DEFAULT 0 COMMENT '账户余额',
  `consume_amount` bigint(20) NOT NULL COMMENT '消费金额',
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户账户表' ROW_FORMAT = DYNAMIC;

INSERT INTO `t_account` VALUES (1, 20, 40, '2023-11-25 20:16:17');

DROP TABLE IF EXISTS `t_order_0`;
CREATE TABLE `t_order_0`  (
  `order_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_id` bigint(20) NOT NULL,
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

INSERT INTO `t_order_0` VALUES ('001000', 1, '2023-11-25 20:08:00');

DROP TABLE IF EXISTS `t_order_1`;
CREATE TABLE `t_order_1`  (
  `order_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_id` bigint(20) NOT NULL,
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

INSERT INTO `t_order_1` VALUES ('001001', 1, '2023-11-25 20:09:18');
  • 生成如下com.xx.wholesale.merchant.busorder.dao.OrderDao文件
package com.xx.wholesale.merchant.busorder.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

@Mapper
public interface OrderDao extends BaseMapper {

    @Select(value = "select * from t_order where user_id=#{userId} and order_id=#{orderId} limit 1")
    public List<Map<String, Object>> queryOrder(@Param("userId") Long userId, @Param("orderId") String orderId);

    @Select(value = "select * from t_account where user_id=#{userId} limit 1")
    public Map<String, Object> queryAccount(@Param("userId") Long userId);
}
  • 生成如下com.xx.wholesale.merchant.busdata.dao.UserDao文件
package com.xx.wholesale.merchant.busdata.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.Map;

@Mapper
public interface UserDao extends BaseMapper {

    @Select(value = "select * from t_user where user_id=#{userId} limit 1")
    public Map<String, Object> selectOne(@Param("userId") Long userId);
}
  • 测试类
package com.xx.wholesale.merchant;

import com.xx.wholesale.merchant.busdata.dao.UserDao;
import com.xx.wholesale.merchant.busorder.dao.OrderDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;
import java.util.Map;

@SpringBootTest
class WholesaleMerchantApplicationTests {

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private UserDao bindDevicerDao;

    /**
     * 【分库分表】
     * 查询既分了库又分了表的订单
     */
    @Test
    void queryOrderShardingLoads() {
        List<Map<String, Object>> map = orderDao.queryOrder(1L, "001000");
        System.out.println(map);
    }

    /**
     * 【分库未分表】
     * 查询用户账户信息,分库但未分表
     */
    @Test
    void queryAccountShardingLoads() {
        Map<String, Object> map = orderDao.queryAccount(1L);
        System.out.println(map);
    }

    /**
     * 【未分库分表】
     * 查询用户基础信息
     */
    @Test
    void queryUserShardingLoads() {
        Map<String, Object> map = bindDevicerDao.selectOne(1L);
        System.out.println(map);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值