Sharding-JDBC 初探(一)

这里是以插入为例进行分析 

配置文件如下

shardingRule:  
  tables:
    t_user: 
      actualDataNodes: ds${0..1}.t_user${0..1}
      databaseStrategy:
        inline:
          shardingColumn: city_id
          algorithmExpression: ds${city_id % 2}
      tableStrategy: 
        inline:
          shardingColumn: sex
          algorithmExpression: t_user${sex % 2}
      keyGeneratorColumnName: id
    t_address: 
      actualDataNodes: ds${0..1}.t_address
      databaseStrategy: 
        inline:
          shardingColumn: lit
          algorithmExpression: ds${lit % 2}
      keyGeneratorColumnName: id
  bindingTables:
    - t_user,t_address
  defaultDataSourceName: ds0
  defaultDatabaseStrategy:
    inline:
      shardingColumn: id
      algorithmExpression: ds${id % 2}
  defaultTableStrategy:
    none:
  props:
    sql.show: true
类 ShardingPreparedStatement

 @Override
    public boolean execute() throws SQLException {
        try {
            //(1)获取路由规则
            Collection<PreparedStatementUnit> preparedStatementUnits = route();
            return new PreparedStatementExecutor(
                    getConnection().getShardingContext().getExecutorEngine(), routeResult.getSqlStatement().getType(), preparedStatementUnits, getParameters()).execute();
        } finally {
            clearBatch();
        }
    }

//(2)路由规则的实现
private Collection<PreparedStatementUnit> route() throws SQLException {
        Collection<PreparedStatementUnit> result = new LinkedList<>();
        //(3)ParsingSQLRouter 中的route解析 跳转到-->步骤2
        routeResult = routingEngine.route(getParameters());
        for (SQLExecutionUnit each : routeResult.getExecutionUnits()) {
            SQLType sqlType = routeResult.getSqlStatement().getType();
            Collection<PreparedStatement> preparedStatements;
            if (SQLType.DDL == sqlType) {
                //DDL语句执行的preparedstatement
                preparedStatements = generatePreparedStatementForDDL(each);
            } else {
                //DML语句执行 的preparedstatement
                preparedStatements = Collections.singletonList(generatePreparedStatement(each));
            }
            routedStatements.addAll(preparedStatements);
            for (PreparedStatement preparedStatement : preparedStatements) {
                replaySetParameter(preparedStatement);
                result.add(new PreparedStatementUnit(each, preparedStatement));
            }
        }
        return result;
    }


//2.路由规则
@Override
    public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
        SQLRouteResult result = new SQLRouteResult(sqlStatement);
        if (sqlStatement instanceof InsertStatement && null != ((InsertStatement) sqlStatement).getGeneratedKey()) {
            processGeneratedKey(parameters, (InsertStatement) sqlStatement, result);
        }
        //跳转 -->步骤3
        RoutingResult routingResult = route(parameters, sqlStatement);
        SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(shardingRule, logicSQL, databaseType, sqlStatement);
        boolean isSingleRouting = routingResult.isSingleRouting();
        if (sqlStatement instanceof SelectStatement && null != ((SelectStatement) sqlStatement).getLimit()) {
            processLimit(parameters, (SelectStatement) sqlStatement, isSingleRouting);
        }
        //拼接sqlbuilder 将占位符使用  ?替代以及真实的sql
        SQLBuilder sqlBuilder = rewriteEngine.rewrite(!isSingleRouting);
        if (routingResult instanceof CartesianRoutingResult) {
            for (CartesianDataSource cartesianDataSource : ((CartesianRoutingResult) routingResult).getRoutingDataSources()) {
                for (CartesianTableReference cartesianTableReference : cartesianDataSource.getRoutingTableReferences()) {
                    result.getExecutionUnits().add(new SQLExecutionUnit(cartesianDataSource.getDataSource(), rewriteEngine.generateSQL(cartesianTableReference, sqlBuilder)));
                }
            }
        } else {
            for (TableUnit each : routingResult.getTableUnits().getTableUnits()) {
                result.getExecutionUnits().add(new SQLExecutionUnit(each.getDataSourceName(), rewriteEngine.generateSQL(each, sqlBuilder)));
            }
        }
        if (showSQL) {
            SQLLogger.logSQL(logicSQL, sqlStatement, result.getExecutionUnits(), parameters);
        }
        return result;
    }


//步骤3 路由实现
private RoutingResult route(final List<Object> parameters, final SQLStatement sqlStatement) {
        //获取表明 没有mapper文件中的sql表明(分表是t_user0 但是mapper中是t_user) 此时表明为t_user
        Collection<String> tableNames = sqlStatement.getTables().getTableNames();
        RoutingEngine routingEngine;
        if (sqlStatement instanceof DDLStatement) {
            routingEngine = new DDLRoutingEngine(shardingRule, parameters, (DDLStatement) sqlStatement); 
        } else if (tableNames.isEmpty()) {
            routingEngine = new DatabaseAllRoutingEngine(shardingRule.getDataSourceMap());
        } else if (1 == tableNames.size() || shardingRule.isAllBindingTables(tableNames) || shardingRule.isAllInDefaultDataSource(tableNames)) {
            //创建 SimpleRoutingEngine引擎 shardingRule 分库分表的规则 parameters 参数 
            routingEngine = new SimpleRoutingEngine(shardingRule, parameters, tableNames.iterator().next(), sqlStatement);
        } else {
            // TODO config for cartesian set
            routingEngine = new ComplexRoutingEngine(shardingRule, parameters, tableNames, sqlStatement);
        }
        //跳转到 步骤4中SimpleRoutingEngine引擎的route方法
        return routingEngine.route();
    }

// 4 SimpleRoutingEngine中的路由规则 
@Override
    public RoutingResult route() {
        //获取与logicTableName(t_user) 相关的分表规则
        TableRule tableRule = shardingRule.getTableRule(logicTableName);
        //根据获取的 tableRule获取分表的规则 也就是配置文件中(databaseStrategy这个属性的value值) 跳转到-->步骤5 准确的实现 (ListShardingValue(logicTableName=t_user, columnName=city_id, values=[0]))
        List<ShardingValue> databaseShardingValues = getDatabaseShardingValues(tableRule);
//与上面的databaseShardingValues 获取规则一样
        List<ShardingValue> tableShardingValues = getTableShardingValues(tableRule);
//获取数据库 跳转到-->步骤7
        Collection<String> routedDataSources = routeDataSources(tableRule, databaseShardingValues);
        Collection<DataNode> routedDataNodes = new LinkedList<>();
        for (String each : routedDataSources) {
//routeTables 与上面个的routeDataSources方法一样的原理
            routedDataNodes.addAll(routeTables(tableRule, each, tableShardingValues));
        }
//获取
        return generateRoutingResult(routedDataNodes);
    }

//步骤5 
private List<ShardingValue> getDatabaseShardingValues(final TableRule tableRule) {
        //获取的就是(根据city_id的值获取库表的分库规则) 跳转到-->步骤6
        ShardingStrategy strategy = shardingRule.getDatabaseShardingStrategy(tableRule);
        return HintManagerHolder.isUseShardingHint() ? getDatabaseShardingValuesFromHint(strategy.getShardingColumns()) : getShardingValues(strategy.getShardingColumns());
    }

//步骤6 获取分库中city_id 的值 获取表明 数据库分库所需要的列的名称以及此列对应的值
private List<ShardingValue> getShardingValues(final Collection<String> shardingColumns) {
        List<ShardingValue> result = new ArrayList<>(shardingColumns.size());
        for (String each : shardingColumns) {
            Optional<Condition> condition = sqlStatement.getConditions().find(new Column(each, logicTableName));
            if (condition.isPresent()) {
                result.add(condition.get().getShardingValue(parameters));
            }
        }
        return result;
    }

//步骤7 
private Collection<String> routeDataSources(final TableRule tableRule, final List<ShardingValue> databaseShardingValues) {
//tableRule获取所有的分库的名称 
        Collection<String> availableTargetDatabases = tableRule.getActualDatasourceNames();
        if (databaseShardingValues.isEmpty()) {
            return availableTargetDatabases;
        }
// 根据availableTargetDatabases  以及databaseShardingValues(ListShardingValue(logicTableName=t_user, columnName=city_id, values=[0]))这份数据获取真正的数据库名称 dosharing()这个方法设计groovy语法
        Collection<String> result = shardingRule.getDatabaseShardingStrategy(tableRule).doSharding(availableTargetDatabases, databaseShardingValues);
        Preconditions.checkState(!result.isEmpty(), "no database route info");
        return result;
    }

//步骤8 获取preparedStatement
private PreparedStatement generatePreparedStatement(final SQLExecutionUnit sqlExecutionUnit) throws SQLException {
//获取连接
        Connection connection = getConnection().getConnection(sqlExecutionUnit.getDataSource(), routeResult.getSqlStatement().getType());
//执行sql
        return returnGeneratedKeys ? connection.prepareStatement(sqlExecutionUnit.getSql(), Statement.RETURN_GENERATED_KEYS)
                : connection.prepareStatement(sqlExecutionUnit.getSql(), resultSetType, resultSetConcurrency, resultSetHoldability);
    }

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

技术王老五

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

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

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

打赏作者

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

抵扣说明:

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

余额充值