springboot 集成sharding-jdbc 5.2.1版本

前提:

功课记录表越来越多,决定使用分表拆分。
采用sharding-jdbc 实现。
不需要分库,只做分表操作

当前环境使用的版本:

java 1.8
spring-cloud Hoxton.SR8
springboot 2.3.4.RELEASE
mybatis-plus 3.4.0

mysql 8.0.27
sharding-jdbc 5.2.1

备注:
本来想使用最新版本,发现阿里云maven仓库没有。
遂使用5.2.1

一、添加sharding-jdbc依赖

		<dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.yaml</groupId>
                    <artifactId>snakeyaml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.33</version>
        </dependency>

二、application.yml 配置

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
      - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
# shardingsphere-jdbc-core-spring-boot-starter 5.2.1 配置
  shardingsphere:
    props:
      sql-show: true  # 打印实际执行的 SQL
      sql-dialect: mysql
    datasource:
      names: d1  # 数据源名称
      d1:  # 数据源具体配置
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver  # MySQL 驱动
        url: jdbc:mysql://192.168.0.178:3301/xsfx_course_db		#MySQL地址
        username: root  # 数据库用户名
        password: root  # 数据库密码
    rules:
      sharding:
        # 分片算法配置
        sharding-algorithms:
          # 按年份分表的分片算法
          table-inline:
            type: CLASS_BASED  # 使用 INLINE 表达式分片
            props:
              strategy: STANDARD
              algorithmClassName: com.xsfx.service.course.provider.config.TableShardingAlgorithmConfig
        # 表分片规则配置
        tables:
          xsfx_course_user_log:  # 逻辑表名
            actual-data-nodes: d1.xsfx_course_user_log, d1.xsfx_course_user_log_$->{2025..2026}  # 实际数据节点,支持动态范围
            table-strategy:  # 分表策略
              standard:
                sharding-column: sharding_column  # 分片字段
                sharding-algorithm-name: table-inline  # 使用分片算法
logging:
  level:
    org.springframework.cloud.sleuth: debug
    org.apache.shardingsphere: DEBUG
    org.apache.shardingsphere.sql: TRACE

注意:
1.起初是因为使用4.0.0版本的sharding-jdbc 分表不支持部分sql语句,所以想换成5.2.1的版本,但是启动一直报错

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

一开始以为是application.yml文件配置出错,但是修改多次配置文件一直没有解决。
后面想到可能是springBoot数据源的问题,springboot数据库连接与sharding-jdbc有冲突
后续查找资料排除这两个类即可正常启动

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
      - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

三、分片算法类

这里分片算法简单写的。
因为数据表已经加了分片字段,接口传参默认会带过来,所以直接匹配到年份相同直接返回

import com.xsfx.common.tools.json.JacksonTool;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Properties;

/**
 * 数据存入规则的实现类
 * @author xsfx
 * @company xsfx
 * @title: HintShardingAlgorithmConfig
 * @projectName xsfx
 * @description: TODO
 * @date 2025/01/09
 */

public class TableShardingAlgorithmConfig implements StandardShardingAlgorithm<Integer> {

    static Logger log = LoggerFactory.getLogger(TableShardingAlgorithmConfig.class);
    @Override
    public String getType() {
        return StandardShardingAlgorithm.super.getType();
    }

    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Integer> preciseShardingValue) {
        for (String str : collection) {
            //dateTimeStr: 分片键sharding_column的值
            Integer dateTimeStr = preciseShardingValue.getValue();
            String yearStr = dateTimeStr.toString();
            if(str.contains(yearStr)){
                return str;
            }
        }
        return "xsfx_course_user_log";
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Integer> rangeShardingValue) {
        log.info("[分表算法doSharding] return Collection<String>");
        log.info("collection is " + JacksonTool.toJson(collection));
        log.info("preciseShardingValue is " + JacksonTool.toJson(rangeShardingValue));
        return null;
    }

    @Override
    public Properties getProps() {
        return null;
    }

    @Override
    public void init(Properties properties) {

    }
}

四、一些SQL修改

自从用了sharding-jdbc,发现有部分SQL无法正常运行。

1.最主要的是有关分片表的sql都得加上分片键的参数

		<!--原来-->
		select sum(al.submit_count) from xsfx_course_user_log al
         <where>
             al.user_id = ul.user_id
             <if test="resourceType != null">
                 and al.resource_type = #{resourceType}
             </if>
             <if test="aId != null">
                 and al.a_id = #{aId}
             </if>
         </where>
         <!--现在-->
         select sum(al.submit_count) from xsfx_course_user_log al
         <where>
             al.user_id = ul.user_id
             <if test="resourceType != null">
                 and al.resource_type = #{resourceType}
             </if>
             <if test="aId != null">
                 and al.a_id = #{aId}
             </if>
             <if test="shardingColumn != null ">
                 and al.sharding_column = #{shardingColumn}
             </if>
         </where>

2.一些mybatis自带修改语句需要重写
例如:updateByPrimaryKeySelective
需要手动将分片加入
不然报错

Can not update sharding value for table `xsfx_course_user_log`.

3.一些子查询使用了聚合函数需要在父级一一列出来,不能在父级直接使用*了

	<!--原来-->
	select c.* from (
        SELECT
        @rank := @rank + 1 AS ranking,
        a.user_id,
        a.course_time
        FROM (
        SELECT
        r.user_id,
        SUM(r.course_time) AS course_time
        FROM
        xsfx_course_user_log r
        <where>
            <if test="templeId != null">
                and r.temple_id = #{templeId}
            </if>
            <if test="courseId != null">
                and r.course_id = #{courseId}
            </if>
            <if test="resourceType != null">
                and r.resource_type = #{resourceType}
            </if>
            <if test="aId != null">
                and r.a_id = #{aId}
            </if>
            <if test="userIds != null and userIds.size() > 0">
                and r.user_id in
                <foreach collection="userIds" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>

            <if test="startDate != null">
                and r.submit_date <![CDATA[ >= ]]> #{startDate}
            </if>
            <if test="endDate != null">
                and r.submit_date <![CDATA[ < ]]> #{endDate}
            </if>
        </where>
        GROUP BY user_id
        ORDER BY course_time DESC
        ) AS a, (SELECT @rank := 0) r) c
        having c.user_id = #{userId}
	<!--修改后-->
	select c.ranking, c.user_id, c.course_time from (
        SELECT
        @rank := @rank + 1 AS ranking,
        a.user_id,
        a.course_time
        FROM (
        SELECT
        r.user_id,
        SUM(r.course_time) AS course_time
        FROM
        xsfx_course_user_log r
        <where>
            <if test="templeId != null">
                and r.temple_id = #{templeId}
            </if>
            <if test="courseId != null">
                and r.course_id = #{courseId}
            </if>
            <if test="resourceType != null">
                and r.resource_type = #{resourceType}
            </if>
            <if test="aId != null">
                and r.a_id = #{aId}
            </if>
            <if test="userIds != null and userIds.size() > 0">
                and r.user_id in
                <foreach collection="userIds" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>

            <if test="startDate != null">
                and r.submit_date <![CDATA[ >= ]]> #{startDate}
            </if>
            <if test="endDate != null">
                and r.submit_date <![CDATA[ < ]]> #{endDate}
            </if>
        </where>
        GROUP BY user_id
        ORDER BY course_time DESC
        ) AS a, (SELECT @rank := 0) r) c
        having c.user_id = #{userId}
<think>好的,我现在需要帮助用户解决在SpringBoot项目中整合ShardingSphere-JDBC-Core5.2.1版本的问题。首先,我需要回顾用户提供的信息和之前的引用内容。用户之前提到的引用是关于SpringBoot集成Sharding-JDBC实现读写分离的测试代码,其中包含了JUnit测试用例,使用@Autowired注入了IUserService,并进行了查询操作。这可能涉及到数据源配置和分片策略的设置。不过用户现在需要的是具体的整合教程或示例代码,特别是针对5.2.1版本。首先,我需要确定ShardingSphere-JDBC5.2.1版本的配置方式是否有变化。根据ShardingSphere的文档,5.x版本相比4.x有一些配置上的调整,比如数据源配置格式和规则定义。因此,正确的配置步骤是关键。接下来,用户可能需要知道如何添加Maven依赖。因为版本不同,依赖的groupId和artifactId可能有变化。ShardingSphere从5.x开始,groupId改为org.apache.shardingsphere,所以需要确认用户是否正确引入依赖。然后,配置数据源。在SpringBoot中,通常通过application.yml或application.properties来配置数据源和分片规则。需要指导用户如何配置主从数据源,读写分离规则,以及可能的其他分片策略。例如,在application.yml中定义数据源名称,主库和从库的连接信息,以及设置读写分离的负载均衡算法。接着,需要处理事务管理器。ShardingSphere-JDBC需要覆盖默认的事务管理器,使用ShardingTransactionManager,这可能涉及到配置类中的Bean定义。此外,用户可能需要进行测试,编写类似之前引用中的测试代码,验证读写分离是否生效。例如,插入数据到主库,然后查询是否从从库读取,或者检查日志确认数据源切换。需要注意的是,用户提供的引用中的代码使用了IUserService和User实体,这可能涉及到MyBatis或JPA的集成。因此,在整合ShardingSphere时,需要确保ORM框架的配置正确,比如MyBatis的Mapper扫描路径或JPA的实体管理。还要考虑版本兼容性问题,SpringBoot版本是否与ShardingSphere-JDBC5.2.1兼容。例如,SpringBoot2.5.x或2.6.x可能需要不同的依赖管理,或者需要排除某些自动配置。最后,用户可能遇到的常见问题,比如数据源未正确加载、分片规则不生效、事务管理问题等,需要给出排查建议,比如检查配置格式、日志级别设置等。总结步骤应该是:添加依赖→配置数据源和规则→配置事务管理器→编写业务代码和测试。同时,提供示例代码片段和配置示例,确保用户能够逐步操作。可能还需要提醒用户注意版本匹配和配置细节,避免常见的配置错误。</think> 以下是在SpringBoot项目中整合ShardingSphere-JDBC-Core 5.2.1版本的完整教程: ### 一、环境准备 1. SpringBoot建议使用2.6.x/2.7.x版本 2. 数据库驱动与连接池(推荐HikariCP) 3. 确保数据库主从架构已搭建完成 ### 二、Maven依赖配置 ```xml <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.2.1</version> </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>4.0.3</version> </dependency> ``` ### 三、配置文件示例(application.yml) ```yaml spring: shardingsphere: datasource: names: master,slave0 master: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://master-host:3306/db username: root password: master-pwd slave0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://slave-host:3306/db username: root password: slave-pwd rules: readwrite-splitting: data-sources: rw-ds: write-data-source-name: master read-data-source-names: slave0 load-balancer-name: round_robin load-balancers: round_robin: type: ROUND_ROBIN props: sql-show: true ``` ### 四、事务管理器配置类 ```java @Configuration public class TransactionConfig { @Autowired private DataSource dataSource; @Bean public PlatformTransactionManager transactionManager() { return new ShardingSphereTransactionManager(dataSource); } } ``` ### 五、读写分离测试示例 ```java @SpringBootTest @Slf4j public class ReadWriteTest { @Autowired private UserMapper userMapper; // 写操作测试 @Test @Transactional public void testWrite() { User user = new User(); user.setUsername("test_user"); userMapper.insert(user); // 该操作会路由到主库 } // 读操作测试 @Test public void testRead() { List<User> users = userMapper.selectList(null); // 该操作会路由到从库 log.info("查询结果: {}", users); } } ``` ### 六、验证关键点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值