强制路由

提示:阅读本文前请详细预读 分库分表

背景

对Sharding-JDBC有初步了解的朋友已经发现了:在编写分片算法的时候,传入的分片键值是来自SQL语句中WHERE条件的。 例如逻辑表t_order如果其数据源分片键为user_id, 分片算法是奇数值路由到db1偶数值路由到db2;表分片键为order_id, 分片算法是奇数值路由到t_order_1偶数值路由到t_order_2,如果执行如下sql语句:

select * from t_order where user_id = 1 and order_id = 2

那么在数据源分片算法的shardingValue参数将会传入1用于分片计算,结果为路由到db1; 表分片算法的shardingValue参数将会传入2用于分片计算,结果为路由到t_order_2。最终SQL为:

select * from db1.t_order_2 where user_id = 1 and order_id = 2

现有一个假设,如果WHERE中没有user_id和order_id的条件,那么是否可以进行分片计算呢?

答案是肯定的。下面就介绍一下Sharding-JDBC对这个问题的解决方法。

基于暗示(Hint)的分片键值管理器

要解决上面的问题,我们使用com.dangdang.ddframe.rdb.sharding.api.HintManager。 该管理器是使用ThreadLocal技术管理分片键值的。 使用例子:

String sql = "SELECT * FROM t_order";
        
try (
        HintManager hintManager = HintManager.getInstance();
        Connection conn = dataSource.getConnection();
        PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
    hintManager.addDatabaseShardingValue("t_order", "user_id", 1);
    hintManager.addTableShardingValue("t_order", "order_id", 2);
    try (ResultSet rs = preparedStatement.executeQuery()) {
        while (rs.next()) {
            ...
        }
    }
}

实例化

// 初始化ThreadLocal中的数据
HintManager hintManager = HintManager.getInstance()

添加分片键值

  • 使用hintManager.addDatabaseShardingValue来添加数据源分片键值
  • 使用hintManager.addTableShardingValue来添加表分片键值

每种分片键值注册方法中有两个重载方法,参数较短的方法可以简化相等条件的分片值注入。

清除添加的分片键值

分片键值保存在ThreadLocal中,所以需要在操作结束时调用hintManager.close()来清除ThreadLocal中的内容。

hintManager实现了AutoCloseable接口,可推荐使用try with resource自动关闭。