论Sharding-jdbc组件 采用 hint-strategy 策略 的实现

因为在项目中,需要用到分库,但不分表。网上找到sharding-jdbc组件,因为业务要求分库,而不是采用数据库字段形式,进行路由。所以需要采用:hint方式,但网上资料少的可怜,而且版本不同,实现起来略有差异,而且网上的实现,注释不全。经过3天的研究,终于了解了hint方式的用法,现在把成果贴出来,供大家参考!

maven 包引入

<dependency>
   <groupId>org.apache.shardingsphere</groupId>
   <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
   <version>4.1.0</version>
</dependency>
<dependency>
   <groupId>org.apache.shardingsphere</groupId>
   <artifactId>sharding-jdbc-spring-namespace</artifactId>
   <version>4.1.0</version>
</dependency>

修改spring配置文件(本例子采用xml配置文件配置)

<!-- 基于暗示(Hint)的分片策略 -->
<bean id="ds0" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
   <property name="driverClassName" value="com.mysql.jdbc.Driver" />
   <property name="url" value="jdbc:mysql://121.229.54.24:3306/wechat01" />
   <property name="username" value="bluemine-dev" />
   <property name="password" value="Qazxsw123" />
</bean>

<bean id="ds1" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
   <property name="driverClassName" value="com.mysql.jdbc.Driver" />
   <property name="url" value="jdbc:mysql://121.229.54.24:3306/wechat02" />
   <property name="username" value="bluemine-dev" />
   <property name="password" value="Qazxsw123" />
</bean>

<!-- 采用自定义暗示分片 -->
<sharding:hint-strategy id="hintDatabaseShardingStrategy" algorithm-ref="myHintStrategy"/>
<!-- 定义数据源 -->
<sharding:data-source id="dataSource">
   <sharding:sharding-rule data-source-names="ds0, ds1">
      <sharding:table-rules>
         <sharding:table-rule logic-table="t_order" actual-data-nodes="ds$->{0..1}.t_order$->{0..1}" database-strategy-ref="hintDatabaseShardingStrategy" table-strategy-ref="hintDatabaseShardingStrategy"/>
      </sharding:table-rules>
   </sharding:sharding-rule>
   <sharding:props>
      <prop key="sql.show">true</prop>
   </sharding:props>
</sharding:data-source>

注意当只分库不分表时,Hint 也需要指定分片表 的数据库分片算法 + 表分片算法, 这一点很不理解

自定义解析类

package com.bluemine.qt.task;

import com.alibaba.druid.util.StringUtils;
import org.apache.shardingsphere.api.sharding.ShardingValue;
import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;
import org.omg.CORBA.OBJ_ADAPTER;
import org.springframework.stereotype.Component;

import java.util.*;

@Component("myHintStrategy")
public class MyHintStrategy implements HintShardingAlgorithm {

   /**
 * 分片方法
 * 会分别对 库 和 表进行路由, 库 和 表分2次进行的.
 * 流程:
 *  程序调用者,指定几号库: hintManager.addDatabaseShardingValue("t_order", 3);  表示:3号库,执行t_order表相关
 *  框架调用: doSharding 方法:
 *      availableTargetNames 为:数据库列表: [ds0, ds1]
 *      shardingValue        为:指定的数据库
 *  程序调用方,指定几号表: hintManager.addTableShardingValue("t_order", 1);     表示: 1号数据表
 *  框架第二次调用doSharding 方法:
 *      availableTargetNames 为:数据表 列表: [t_order0, t_order1];
 *      shardingValue        为:指定的数据表
 *  依次类推, 如果程序调用方,还有其他表的指定,则框架还好再次调用此方法.
 *
 * @param availableTargetNames
 * @param shardingValue
 * @return
 */
    @Override
    public Collection<String> doSharding(Collection availableTargetNames, HintShardingValue shardingValue) {

        System.out.println("shardingValue=" + shardingValue);
        System.out.println("availableTargetNames=" + availableTargetNames);

        List<String> shardingResult = new ArrayList<>();

        Iterator i = availableTargetNames.iterator();
        while (i.hasNext()){
            String targetName = (String) i.next();
            String suffix = targetName.substring(targetName.length() - 1);
            if (StringUtils.isNumber(suffix)) {
                // hint分片算法的ShardingValue有两种具体类型:
                // ListShardingValue和RangeShardingValue
                // 使用哪种取决于HintManager.addDatabaseShardingValue(String, String, ShardingOperator,...),ShardingOperator的类型
                Iterator j = shardingValue.getValues().iterator();
                while (j.hasNext()){
                    Integer value = (Integer) j.next();
                    if (value % 2 == Integer.parseInt(suffix)) {
                        shardingResult.add(targetName);
                    }
                }
            }
        }
        return shardingResult;
    }
}

调用入口代码(junit 用法,自行百度)

@Test
   public void shardingDB() throws Exception {

      HintManager.clear();
      HintManager hintManager = HintManager.getInstance();

      // 方式1:
      // 下面2句话的意思时: 向3号库中的1号 t_order 表执行sql
      // 选择具体的数据库, 3 可以简单理解为: 3号库,如果只有2个库, 那么可以根据2取模,落到 1号库上面
      hintManager.addDatabaseShardingValue("t_order", 3);
      // 同理:一个数据库中可以有多张t_order表, 1 可以理解为: 1号表.
      hintManager.addTableShardingValue("t_order", 1);

      // 方式2
      // 直接指定对应具体的数据库
//    hintManager.setDatabaseShardingValue(0);

      Order order = new Order();
      order.setUserId(2);
      order.setName("测试00");
      orderMapper.insert(order);

      HintManager.clear();
   }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

绿竹痕

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

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

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

打赏作者

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

抵扣说明:

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

余额充值