多数据源下配置shardingjdbc,导致主数据源失效的场景

在配置ShardingJDBC进行数据库分表后,主数据源在进行主业务操作时失效。问题源于数据源配置和依赖版本。通过升级ShardingJDBC依赖至4.1版本,解决了主数据源未被正确识别的问题。在新版本中,主数据源操作无需额外注解,分表数据源操作需添加@DS(sharding)注解。
摘要由CSDN通过智能技术生成

配置主数据源和通过shardingjdbc进行分表配置

本人在此次分表过程中遇到了这样的事情,主业务都在主数据源上,分表的数据源和主数据源不是同一个数据库。一切配置好后,分表插入数据也没有问题,后面测试主业务场景时,发现主数据源失效,楞是花了我大半天时间才找到原因,在这里分享下,希望你们不会遇到。

先看主要配置信息

  1. 引入需要的依赖
		<dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>

        <!--依赖dynamic-datasource-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.2.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-core-common</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>
  1. 进行数据源配置
spring:
  application:
    # 应用名称
    name: weygy
  profiles:
    # 环境配置
    active: dev
  main:
    allow-bean-definition-overriding: true
  datasource:
    dynamic:
      primary: master
      datasource:
        master:
          username: root
          password: root
          url: jdbc:mysql://127.0.0.1:3306/center?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
          driver-class-name: com.mysql.cj.jdbc.Driver
  shardingsphere:
    datasource:
      names: logging
      logging:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/report?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
        username: root
        password: root
        type: com.zaxxer.hikari.HikariDataSource
    sharding:
      #指定data表的数据分布情况。
      #data_$->{1..3}:logging.data_1;logging.data_2;
      tables:
        data:
          actual-data-nodes: logging.data_$->{1..3}
          #指定表的主键生成策略SNOWFLAKE
          key-generator:
            column: data_id
            type: SNOWFLAKE
          #指定表的分片策略,包括分片键和分片算法
          table-strategy:
            inline:
              sharding-column: data_id
              algorithm-expression: data_$->{data_id % 3 + 1}

这里分了三张表

  1. 添加Dynamic-datasource的动态数据源配置类
package cn.logging.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.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;

/**
 * @ClassName: DataSourceConfiguration
 * @Description: Dynamic-datasource的动态数据源配置类
 * @author: Sir
 * @date: 2023/4/18 17:55
 * @version: 1.0
 **/
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class DataSourceConfiguration {

    @Resource
    private DynamicDataSourceProperties properties;

    /**
     * shardingjdbc有四种数据源,需要根据业务注入不同的数据源
     *
     * <p>1. 未使用分片, 脱敏的名称(默认): shardingDataSource;
     * <p>2. 主从数据源: masterSlaveDataSource;
     * <p>3. 脱敏数据源:encryptDataSource;
     * <p>4. 影子数据源:shadowDataSource
     * <p>5. 分片使用数据源:shardingSphereDataSource
     *
     */
    @Lazy
    @Resource
    private DataSource shardingSphereDataSource;

    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
                dataSourceMap.put("sharding", shardingSphereDataSource);
                //打开下面的代码可以把 shardingjdbc 管理的数据源也交给动态数据源管理 (根据自己需要选择开启)
                //dataSourceMap.putAll(((MasterSlaveDataSource) masterSlaveDataSource).getDataSourceMap());
                return dataSourceMap;
            }
        };
    }

    /**
     * 将动态数据源设置为首选的
     * 当spring存在多个数据源时, 自动注入的是首选的对象
     * 设置为主要的数据源之后,就可以支持shardingjdbc原生的配置方式了
     */
    @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;
    }
}

  1. 场景测试

分表的插入数据场景,需要加上:@DS(“sharding”)

    @Override
    @DS("sharding")
    public ResultDataVo reportEvent() {
        ReportData data = new ReportData();
        loggingService.reportEvent(data);
        return getVo(dto);
    }

主业务插入数据场景:不用加注解,默认进入

@Service
public class loggingEventServiceImpl implements loggingEventService {

    @Autowired
    private loggingEventMapper loggingEventMapper;

    @Override
    public void insertloggingEvent(loggingEventPo loggingEventPo) {
        loggingEventMapper.insertloggingEvent(loggingEventPo);
    }
}

出现问题的场景

### Cause: java.sql.SQLSyntaxErrorException: Table 'logging_report.event' doesn't exist

这里出现该问题的主要原因可以在:Dynamic-datasource的动态数据源配置类中查看出来,这里只进入了第一个断点,没有进入第二个断点
在这里插入图片描述

问题修改

修改方法将依赖版本增加到4.1
在这里插入图片描述

此时进入第二个断点,加载数据源。主数据源使用不需要加注解,默认主数据源,分表的数据源使用需要加注解:@DS(“sharding”)
在这里插入图片描述

后续又遇到了其它场景
在这里插入图片描述

可能是因为在配置多数据源时没有正确指定数据源的名称,导致分页插件无法识别默认的数据源。需要在配置文件中明确指定数据源的名称,例如: ``` mybatis-plus: configuration: map-underscore-to-camel-case: true default-fetch-size: 100 default-statement-timeout: 30 global-config: db-config: id-type: auto logic-delete-value: 1 logic-not-delete-value: 0 field-strategy: not_empty db-type: mysql banner: false mapper-locations: classpath:/mapper/**Mapper.xml type-aliases-package: com.example.demo.entity # 指定数据源名称 datasource: druid: master: url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver slave: url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver ``` 然后在分页插件中指定数据源名称: ``` @Configuration public class MybatisPlusConfig { @Autowired private DruidDataSource masterDataSource; @Autowired private DruidDataSource slaveDataSource; /** * 分页插件 */ @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 指定数据源名称 paginationInterceptor.setSqlParser(new TenantSqlParser().setTenantHandler(new MyTenantHandler()).setDataSource("master")); return paginationInterceptor; } /** * 多数据源配置 */ @Bean @Primary public DynamicDataSource dynamicDataSource() { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put("master", masterDataSource); targetDataSources.put("slave", slaveDataSource); DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.setDefaultTargetDataSource(masterDataSource); return dynamicDataSource; } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

焚目圣僧渡众生

你的 一角将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值