前一篇博文中提到JdbcTeplate执行SQL的第一步首先是创建连接对象。
1,DataSourceUtils.getConnection(obtainDataSource()); 创建连接,该处只是获得连接对象并未真正建立连接
2,由“ Connection ”创建对应的Connection.createStatement()创建对应的Statement
3,执行Statement的execute(final String sql)方法
4,返回结果集
io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource.getConnection() 源码如下
@Override
public ShardingConnection getConnection() throws SQLException {
return new ShardingConnection(shardingContext); --继承了Connection
}
io.shardingjdbc.core.jdbc.core.connection.ShardingConnection.createStatement() 源码如下
@Override
public Statement createStatement() throws SQLException {
return new ShardingStatement(this);
}
即执行io.shardingjdbc.core.jdbc.core.statement.ShardingStatement。执行(SQL)方法,源码如下
io.shardingjdbc.core.jdbc.core.statement.ShardingStatement.execute(sql)
@Override
public boolean execute(final String sql) throws SQLException {
try {
return generateExecutor(sql).execute();
} finally {
currentResultSet = null;
}
}
由此可见执行SQL时需要调用对应执行器的execute()方法,具体调用源码如下。
io.shardingjdbc.core.jdbc.core.statement.ShardingStatement.generateExecutor(sql)
private StatementExecutor generateExecutor(final String sql) throws SQLException {
clearPrevious();
routeResult = new StatementRoutingEngine(connection.getShardingContext()).route(sql);
Collection statementUnits = new LinkedList<>();
for (SQLExecutionUnit each : routeResult.getExecutionUnits()) {
Collection connections;
SQLType sqlType = routeResult.getSqlStatement().getType();
if (SQLType.DDL == sqlType) {
connections = connection.getConnectionsForDDL(each.getDataSource());
} else {
connections = Collections.singletonList(connection.getConnection(each.getDataSource(), routeResult.getSqlStatement().getType()));
}
for (Connection connection : connections) {
Statement statement = connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
replayMethodsInvocation(statement);
statementUnits.add(new StatementUnit(each, statement));
routedStatements.add(statement);
}
}
return new StatementExecutor(connection.getShardingContext().getExecutorEngine(), routeResult.getSqlStatement().getType(), statementUnits);
}
总结:上述源码重点描述了sharding-jdbc如何进行SQL解析,SQL改写,SQL路由。该代码拆分为如下3步子功能:
1、根据sql获取对应的sql路由结果,即获取该sql具体和哪个datasource建立链接
SQLRouteResult routeResult = new StatementRoutingEngine(connection.getShardingContext()).route(sql);
routeResult 即为sql路由结果,即获取该sql应该和哪个datasource建立连接??
2、根绝sql路由结果和对应的datasource建立连接
Collection
SQLType sqlType = routeResult.getSqlStatement().getType();
if (SQLType.DDL == sqlType) {
connections = connection.getConnectionsForDDL(each.getDataSource()); 真正的建立连接
} else {
connections = Collections.singletonList(connection.getConnection(each.getDataSource(), routeResult.getSqlStatement().getType())); 真正的建立连接
}
3、sql执行器执行对应的sql