改写步骤图
书接上文
获取完路由上下文后,从prepare方法中来到了executeRewrite方法,其源码如下:
private Collection<ExecutionUnit> executeRewrite(String sql, List<Object> parameters, RouteContext routeContext) {this.registerRewriteDecorator();SQLRewriteContext sqlRewriteContext = this.rewriter.createSQLRewriteContext(sql, parameters, routeContext.getSqlStatementContext(), routeContext);return routeContext.getRouteResult().getRouteUnits().isEmpty() ? this.rewrite(sqlRewriteContext) : this.rewrite(routeContext, sqlRewriteContext);}
显然,这个方法中进行了SQL改写(rewrite),这正是本节的重点,以下的分析将会围绕着这个方法进行展开。
注册
实现,先进行了重写装饰器的注册,该方法源码如下:
即在SQLRewriteEntry中注册SQLRewriteContextDecorator的对象。
createSQLRewriteContext
回到executeRewrite方法中,在执行完registerRewriteDecorator后将会调用createSQLRewriteContext,这里根据语义判断应该是创建SQLRewrite的上下文,其源码如下:
decorate
private void decorate(Map<BaseRule, SQLRewriteContextDecorator> decorators, SQLRewriteContext sqlRewriteContext, RouteContext routeContext) {BaseRule rule;SQLRewriteContextDecorator decorator;for(Iterator var4 = decorators.entrySet().iterator(); var4.hasNext(); decorator.decorate(rule, this.properties, sqlRewriteContext)) {Entry<BaseRule, SQLRewriteContextDecorator> entry = (Entry)var4.next();rule = (BaseRule)entry.getKey();decorator = (SQLRewriteContextDecorator)entry.getValue();if (decorator instanceof RouteContextAware) {((RouteContextAware)decorator).setRouteContext(routeContext);}}}
继续追:
public void decorate(ShardingRule shardingRule, ConfigurationProperties properties, SQLRewriteContext sqlRewriteContext) {Iterator var4 = (new ShardingParameterRewriterBuilder(shardingRule, this.routeContext)).getParameterRewriters(sqlRewriteContext.getSchemaMetaData()).iterator();while(var4.hasNext()) {ParameterRewriter each = (ParameterRewriter)var4.next();if (!sqlRewriteContext.getParameters().isEmpty() && each.isNeedRewrite(sqlRewriteContext.getSqlStatementContext())) {each.rewrite(sqlRewriteContext.getParameterBuilder(), sqlRewriteContext.getSqlStatementContext(), sqlRewriteContext.getParameters());}}sqlRewriteContext.addSQLTokenGenerators((new ShardingTokenGenerateBuilder(shardingRule, this.routeContext)).getSQLTokenGenerators());}
这里判断一下是否需要重写且参数为空,如果是则进行重写。
即把所有的重写结果放入到sqlRewrite上下文中。
rewrite
返回到executeRewrite,这里进行了的上下文信息已经装填完成:
即将开始真正的重写。
其源码如下:
private Collection<ExecutionUnit> rewrite(RouteContext routeContext, SQLRewriteContext sqlRewriteContext) {Collection<ExecutionUnit> result = new LinkedHashSet();Iterator var4 = (new SQLRouteRewriteEngine()).rewrite(sqlRewriteContext, routeContext.getRouteResult()).entrySet().iterator();while(var4.hasNext()) {Entry<RouteUnit, SQLRewriteResult> entry = (Entry)var4.next();result.add(new ExecutionUnit(((RouteUnit)entry.getKey()).getDataSourceMapper().getActualName(), new SQLUnit(((SQLRewriteResult)entry.getValue()).getSql(), ((SQLRewriteResult)entry.getValue()).getParameters())));}return result;}
继续追踪:
public Map<RouteUnit, SQLRewriteResult> rewrite(SQLRewriteContext sqlRewriteContext, RouteResult routeResult) {Map<RouteUnit, SQLRewriteResult> result = new LinkedHashMap(routeResult.getRouteUnits().size(), 1.0F);Iterator var4 = routeResult.getRouteUnits().iterator();while(var4.hasNext()) {RouteUnit each = (RouteUnit)var4.next();result.put(each, new SQLRewriteResult((new RouteSQLBuilder(sqlRewriteContext, each)).toSQL(), this.getParameters(sqlRewriteContext.getParameterBuilder(), routeResult, each)));}return result;}
这里具体是根据RouteUnit的分组进行重写(字符串拼接),详细代码在toSQL中,其源码如下:
public final String toSQL() {if (this.context.getSqlTokens().isEmpty()) {return this.context.getSql();} else {Collections.sort(this.context.getSqlTokens());StringBuilder result = new StringBuilder();result.append(this.context.getSql().substring(0, ((SQLToken)this.context.getSqlTokens().get(0)).getStartIndex()));Iterator var2 = this.context.getSqlTokens().iterator();while(var2.hasNext()) {SQLToken each = (SQLToken)var2.next();result.append(this.getSQLTokenText(each));result.append(this.getConjunctionText(each));}return result.toString();}}
总结
最终拼凑好的语句信息都放在了ExecutionUnit和SQLUnit中:
