sharding-jdbc多库多表路由
找到这个类com.dangdang.ddframe.rdb.sharding.routing.PreparedStatementRoutingEngine
找到这里
/**
* SQL路由.
* 当第一次路由时进行SQL解析,之后的路由复用第一次的解析结果.
*
* @param parameters SQL中的参数
* @return 路由结果
*/
public SQLRouteResultroute(final List parameters) {//sql路由业务方法
if (null ==sqlStatement) {
sqlStatement =sqlRouter.parse(logicSQL, parameters.size());
}
return sqlRouter.route(logicSQL, parameters, sqlStatement);
}
return sqlRouter.route(logicSQL, parameters, sqlStatement);
@Override
public SQLRouteResultroute(final String logicSQL, final List parameters, final SQLStatement sqlStatement) {
final Context context = MetricsContext.start("Route SQL");
SQLRouteResult result =new SQLRouteResult(sqlStatement);
// 如果是insert语句去生成分布式逐渐的逻辑
if (sqlStatementinstanceof InsertStatement &&null != ((InsertStatement) sqlStatement).getGeneratedKey()) {
processGeneratedKey(parameters, (InsertStatement) sqlStatement, result);
}
RoutingResult routingResult = route(parameters, sqlStatement);
RoutingResult routingResult = route(parameters, sqlStatement);
private RoutingResultroute(final List parameters, final SQLStatement sqlStatement) {
Collection tableNames = sqlStatement.getTables().getTableNames();
RoutingEngine routingEngine;
// 如果表集合是1,或者是绑定表路由就走简单路由规则
if (1 == tableNames.size() ||shardingRule.isAllBindingTables(tableNames)) {
routingEngine =new SimpleRoutingEngine(shardingRule, parameters, tableNames.iterator().next(), sqlStatement);//单表路由
}else {
// TODO 可配置是否执行笛卡尔积
routingEngine =new ComplexRoutingEngine(shardingRule, parameters, tableNames, sqlStatement);
}
return routingEngine.route();//tianhe TODO 笛卡尔积
}
进入到这个方法com.dangdang.ddframe.rdb.sharding.routing.type.complex.ComplexRoutingEngine#route
@Override
public RoutingResultroute() {
Collection result =new ArrayList<>(logicTables.size());
Collection bindingTableNames =new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
for (String each :logicTables) {
// 根据逻辑表查找分片规则
Optional tableRule =shardingRule.tryFindTableRule(each);
if (tableRule.isPresent()) {
// 如果绑定表名不包含逻辑表走简单路由
if (!bindingTableNames.contains(each)) {
result.add(new SimpleRoutingEngine(shardingRule, parameters, tableRule.get().getLogicTable(), sqlStatement).route());
}
// 根据逻辑表找绑定表规则配置,如果有走绑定表规则配置路由
Optional bindingTableRule =shardingRule.findBindingTableRule(each);
if (bindingTableRule.isPresent()) {
bindingTableNames.addAll(Lists.transform(bindingTableRule.get().getTableRules(), new Function() {
@Override
public Stringapply(final TableRule input) {
return input.getLogicTable();
}
}));
}
}
}
log.trace("mixed tables sharding result: {}", result);
if (result.isEmpty()) {
throw new ShardingJdbcException("Cannot find table rule and default data source with logic tables: '%s'", logicTables);
}
if (1 == result.size()) {
return result.iterator().next();
}
// 创建混合多库表路由结果
return new CartesianRoutingEngine(result).route();
}
return new CartesianRoutingEngine(result).route();
笛卡尔积路由引擎
/**
* 笛卡尔积的库表路由.
*
* @author zhangliang
*/
@RequiredArgsConstructor
@Slf4j
public final class CartesianRoutingEngineimplements RoutingEngine {
// 路由结果
private final CollectionroutingResults;
返回到这里
@Override
public CartesianRoutingResultroute() {
// 创建笛卡尔积路由对象
CartesianRoutingResult result =new CartesianRoutingResult();
// 遍历数据源和逻辑表集合的映射关系
for (Entry> entry : getDataSourceLogicTablesMap().entrySet()) {
// 获取物理表集合
List> actualTableGroups = getActualTableGroups(entry.getKey(), entry.getValue());
// 根据数据源和物理表集合获取具体的执行单元
List> tableUnitGroups = toTableUnitGroups(entry.getKey(), actualTableGroups);
result.merge(entry.getKey(), getCartesianTableReferences(Sets.cartesianProduct(tableUnitGroups)));
}
log.trace("cartesian tables sharding result: {}", result);
return result;
}
组装笛卡尔积结果集
Sets.cartesianProduct(tableUnitGroups)
组装笛卡尔积路由组
getCartesianTableReferences(Sets.cartesianProduct(tableUnitGroups))
组装笛卡尔积路由结果对象
result.merge
以上介绍了多库表sql路由。
返回到这里
@Override
public SQLRouteResultroute(final String logicSQL, final List parameters, final SQLStatement sqlStatement) {
final Context context = MetricsContext.start("Route SQL");
SQLRouteResult result =new SQLRouteResult(sqlStatement);
// 如果是insert语句去生成分布式逐渐的逻辑
if (sqlStatementinstanceof InsertStatement &&null != ((InsertStatement) sqlStatement).getGeneratedKey()) {
processGeneratedKey(parameters, (InsertStatement) sqlStatement, result);
}
// 进行sql路由返回路由结果
RoutingResult routingResult = route(parameters, sqlStatement);
SQLRewriteEngine rewriteEngine =new SQLRewriteEngine(shardingRule, logicSQL, sqlStatement);
boolean isSingleRouting = routingResult.isSingleRouting();
if (sqlStatementinstanceof SelectStatement &&null != ((SelectStatement) sqlStatement).getLimit()) {
processLimit(parameters, (SelectStatement) sqlStatement, isSingleRouting);
}
SQLBuilder sqlBuilder = rewriteEngine.rewrite(!isSingleRouting);
if (routingResultinstanceof 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)));
}
}
MetricsContext.stop(context);
if (showSQL) {
SQLLogger.logSQL(logicSQL, sqlStatement, result.getExecutionUnits(), parameters);
}
return result;
}
后面sql改写的部分下次再介绍。
说到最后
以上是混合多库多表路由源码解析,仅供参考。
关注微信公众号
加入技术微信群