这里是以插入为例进行分析
配置文件如下
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);
}