.
InsertClauseShardingConditionEngine(处理insert语句)
/**
* <pre>
* // 插入有多少行,有多少条ShardingCondition
* List = List<ShardingCondition> : [
* ShardingCondition { // 插入某一行数据,提取出来的sharding条件
* routeValues : [ // 根据多个列sharding,会有多个值
* ListRouteValue {columnName : "id", tableName : "tb_users", values : ["1"]}
* ListRouteValue {columnName : "city_id", tableName : "tb_users", values : ["2"]}
* ListRouteValue {columnName : "gen_seq_no", tableName : "tb_users", values : ["45678909876545676789"]} // 自动生成,即:用户编写的sql不包含gen_seq_no字段
* ]
* }
* ]
* </pre>
*/
// org.apache.shardingsphere.sharding.route.engine.condition.engine.InsertClauseShardingConditionEngine#createShardingConditions
public final class InsertClauseShardingConditionEngine {
private final ShardingRule shardingRule;
/**
*/
public List<ShardingCondition> createShardingConditions(final InsertStatementContext insertStatementContext, final List<Object> parameters) {
// 单次插入多少行,ShardingCondition列表就有多少条
List<ShardingCondition> result = new LinkedList<>();
String tableName = insertStatementContext.getSqlStatement().getTable().getTableName().getIdentifier().getValue();
// 获取要插入的字段列表,删除掉自动生成的key字段
Collection<String> columnNames = getColumnNames(insertStatementContext);
// 遍历要插入的行列表
for (InsertValueContext each : insertStatementContext.getInsertValueContexts()) {
// 处理某一行,调用 createShardingCondition -- 可以多个字段同时作为sharding字段
result.add(createShardingCondition(tableName, columnNames.iterator(), each, parameters));
}
Optional<GeneratedKeyContext> generatedKey = insertStatementContext.getGeneratedKeyContext();
// 如果有自动生成的key,即:用户编写的sql里面没有key字段
if (generatedKey.isPresent() && generatedKey.get().isGenerated()) {
// 生成key值列表,如:uuid列表、雪花值列表
generatedKey.get().getGeneratedValues().addAll(getGeneratedKeys(tableName, insertStatementContext.getSqlStatement().getValueListCount()));
// 如果该生成的key字段是sharding字段
if (shardingRule.isShardingColumn(generatedKey.get().getColumnName(), tableName)) {
// 把生成的值添加到ShardingCondition列表的value里面
appendGeneratedKeyCondition(generatedKey.get(), tableName, result);
}
}
return result;
}
private Collection<String> getColumnNames(final InsertStatementContext insertStatementContext) {
Optional<GeneratedKeyContext> generatedKey = insertStatementContext.getGeneratedKeyContext();
if (generatedKey.isPresent() && generatedKey.get().isGenerated()) {
Collection<String> result = new LinkedList<>(insertStatementContext.getColumnNames());
result.remove(generatedKey.get().getColumnName()); // 删除掉自动生成的key字段
return result;
}
return insertStatementContext.getColumnNames();
}
private ShardingCondition createShardingCondition(final String tableName, final Iterator<String> columnNames, final InsertValueContext insertValueContext, final List<Object> parameters) {
// 每行数据会创建一个ShardingCondition对象
ShardingCondition result = new ShardingCondition();
SPITimeService timeService = new SPITimeService();
// 遍历“列”列表 -- 可以多个字段同时作为sharding字段
for (ExpressionSegment each : insertValueContext.getValueExpressions()) {
String columnName = columnNames.next();
if (shardingRule.isShardingColumn(columnName, tableName)) { // 某列是sharding列
if (each instanceof SimpleExpressionSegment) {
// 获取对应列的值
result.getRouteValues().add(new ListRouteValue<>(columnName, tableName, Collections.singletonList(getRouteValue((SimpleExpressionSegment) each, parameters))));
} else if (ExpressionConditionUtils.isNowExpression(each)) {
result.getRouteValues().add(new ListRouteValue<>(columnName, tableName, Collections.singletonList(timeService.getTime())));
} else if (ExpressionConditionUtils.isNullExpression(each)) {
throw new ShardingSphereException("Insert clause sharding column can't be null.");
}
}
}
return result;
}
private Comparable<?> getRouteValue(final SimpleExpressionSegment expressionSegment, final List<Object> parameters) {
Object result;
if (expressionSegment instanceof ParameterMarkerExpressionSegment) {
// 获取绑定的参数值
result = parameters.get(((ParameterMarkerExpressionSegment) expressionSegment).getParameterMarkerIndex());
} else {
result = ((LiteralExpressionSegment) expressionSegment).getLiterals();
}
Preconditions.checkArgument(result instanceof Comparable, "Sharding value must implements Comparable.");
return (Comparable) result;
}
private Collection<Comparable<?>> getGeneratedKeys(final String tableName, final int valueListCount) {
return IntStream.range(0, valueListCount).mapToObj(i -> shardingRule.generateKey(tableName)).collect(Collectors.toCollection(LinkedList::new));
}
private void appendGeneratedKeyCondition(final GeneratedKeyContext generatedKey, final String tableName, final List<ShardingCondition> shardingConditions) {
Iterator<Comparable<?>> generatedValuesIterator = generatedKey.getGeneratedValues().iterator();
for (ShardingCondition each : shardingConditions) { // 把生成的值补充到 ShardingCondition
each.getRouteValues().add(new ListRouteValue<>(generatedKey.getColumnName(), tableName, Collections.<Comparable<?>>singletonList(generatedValuesIterator.next())));
}
}
}
.