大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说php视频解析源码_自动阅读源码,希望您对编程的造诣更进一步.
前言
本章从一个select语句的执行,进入sharding-jdbc的第一步解析。
private static void select(DataSource dataSource, long userId, long orderId) throws SQLException {
Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement =
connection.prepareStatement("select * from t_order where user_id = ? and order_id = ?");
preparedStatement.setLong(1, userId);
preparedStatement.setLong(2, orderId);
preparedStatement.execute();
ResultSet resultSet = preparedStatement.getResultSet();
while (resultSet.next()) {
System.out.print("order_id = " + resultSet.getLong(1) + ",");
System.out.print("user_id = " + resultSet.getLong(2) + ",");
System.out.print("address_id = " + resultSet.getLong(3) + ",");
System.out.println("status = " + resultSet.getString(4));
}
resultSet.close();
preparedStatement.close();
connection.close();
}
一、ShardingConnection
ShardingDataSource通过构造方法创建ShardingConnection
。
public class ShardingDataSource extends AbstractDataSourceAdapter {
private final ShardingRuntimeContext runtimeContext;
public ShardingDataSource(final Map<String, DataSource> dataSourceMap, final ShardingRule shardingRule, final Properties props) throws SQLException {
super(dataSourceMap);
checkDataSourceType(dataSourceMap);
runtimeContext = new ShardingRuntimeContext(dataSourceMap, shardingRule, props, getDatabaseType());
}
@Override
public final ShardingConnection getConnection() {
// TransactionTypeHolder持有ThreadLocal,用于设置事务类型,默认LOCAL
return new ShardingConnection(getDataSourceMap(), runtimeContext, TransactionTypeHolder.get());
}
}
ShardingConnection
构造方法。
@Getter
public final class ShardingConnection extends AbstractConnectionAdapter {
// 数据源map
private final Map<String, DataSource> dataSourceMap;
// sharding-jdbc运行上下文
private final ShardingRuntimeContext runtimeContext;
// 事务类型 默认LOCAL
private final TransactionType transactionType;
// 事务管理器 默认是null
private final ShardingTransactionManager shardingTransactionManager;
public ShardingConnection(final Map<String, DataSource> dataSourceMap, final ShardingRuntimeContext runtimeContext, final TransactionType transactionType) {
this.dataSourceMap = dataSourceMap;
this.runtimeContext = runtimeContext;
this.transactionType = transactionType;
shardingTransactionManager = runtimeContext.getShardingTransactionManagerEngine().getTransactionManager(transactionType);
}
}
ShardingConnection
的继承关系与ShardingDataSource
类似。AbstractUnsupportedOperationConnection
实现了不支持的Connection
接口方法(抛出异常),AbstractConnectionAdapter
是sharding-jdbcConnection
实现类的抽象父类,提供一些方法的默认实现。
二、ShardingPreparedStatement
ShardingConnection
创建ShardingPreparedStatement
,把自己和sql传入ShardingPreparedStatement
构造方法。
@Getter
public final class ShardingConnection extends AbstractConnectionAdapter {
@Override
public PreparedStatement prepareStatement(final String sql) throws SQLException {
return new ShardingPreparedStatement(this, sql);
}
}
ShardingPreparedStatement
构造方法。
public final class ShardingPreparedStatement extends AbstractShardingPreparedStatementAdapter {
@Getter
private final ShardingConnection connection;
private final String sql;
@Getter
private final ParameterMetaData parameterMetaData;
private final BasePrepareEngine prepareEngine;
private final PreparedStatementExecutor preparedStatementExecutor;
private final BatchPreparedStatementExecutor batchPreparedStatementExecutor;
private final Collection<Comparable<?>> generatedValues = new LinkedList<>();
private ExecutionContext executionContext;
private ResultSet currentResultSet;
public ShardingPreparedStatement(final ShardingConnection connection, final String sql) throws SQLException {
this(connection, sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT, false);
}
private ShardingPreparedStatement(final ShardingConnection connection, final String sql,
final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final boolean returnGeneratedKeys) throws SQLException {
if (Strings.isNullOrEmpty(sql)) {
throw new SQLException(SQLExceptionConstant.SQL_STRING_NULL_OR_EMPTY);
}
this.connection = connection;
this.sql = sql;
ShardingRuntimeContext runtimeContext = connection.getRuntimeContext();
// ParameterMetaData
parameterMetaData = new ShardingParameterMetaData(runtimeContext.getSqlParserEngine(), sql);
// PreparedQueryPrepareEngine
prepareEngine = new PreparedQueryPrepareEngine(runtimeContext.getRule().toRules(), runtimeContext.getProperties(), runtimeContext.getMetaData(), runtimeContext.getSqlParserEngine());
// PreparedStatementExecutor
preparedStatementExecutor = new PreparedStatementExecutor(resultSetType, resultSetConcurrency, resultSetHoldability, returnGeneratedKeys, connection);
// BatchPreparedStatementExecutor
batchPreparedStatementExecutor = new BatchPreparedStatementExecutor(resultSetType, resultSetConcurrency, resultSetHoldability, returnGeneratedKeys, connection);
}
}
1、ParameterMetaData
ParameterMetaData
占位符参数的元数据。 构造时传入了ShardingRuntimeContext
持有的SQLParserEngine
。
对于ShardingParameterMetaData
来说只支持一个方法getParameterCount
,getParameterCount
获取sql中占位符个数。
@RequiredArgsConstructor
public final class ShardingParameterMetaData extends AbstractUnsupportedOperationParameterMetaData {
private final SQLParserEngine sqlParserEngine;
private final String sql;
@Override
public int getParameterCount() {
return sqlParserEngine.parse(sql, true).getParameterCount();
}
}
2、BasePrepareEngine
BasePrepareEngine
非常重要,在它的唯一public方法中实现了解析、路由、重写三个重要步骤。
@RequiredArgsConstructor
public abstract class BasePrepareEngine {
private final Collection<BaseRule> rules;
private final ConfigurationProperties properties;
private final ShardingSphereMetaData metaData;
private final DataNodeRouter router;
private final SQLRewriteEntry rewriter;
public BasePrepareEngine(final Collection<BaseRule> rules, final ConfigurationProperties properties, final ShardingSphereMetaData metaData, final SQLParserEngine parser) {
this.rules = rules;
this.properties = properties;
this.metaData = metaData;
router = new DataNodeRouter(metaData, properties, parser);
rewriter = new SQLRewriteEntry(metaData.getSchema(), properties);
}
}
BasePrepareEngine
构造方法,创建DataNodeRouter
,负责路由;创建SQLRewriteEntry
,负责创建SQLRewriteContext
重写上下文。
BasePrepareEngine
的实现类有两个:
PreparedQueryPrepareEngine
:处理PrepareStatement
。SimpleQueryPrepareEngine
:处理Statement
。
3、PreparedStatementExecutor
PreparedStatementExecutor
继承AbstractStatementExecutor
抽象类负责执行sql,先看一眼构造方法,直接跳过。
public final class PreparedStatementExecutor extends AbstractStatementExecutor {
@Getter
private final boolean returnGeneratedKeys;
public PreparedStatementExecutor(
final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final boolean returnGeneratedKeys, final ShardingConnection shardingConnection) {
super(resultSetType, resultSetConcurrency, resultSetHoldability, shardingConnection);
this.returnGeneratedKeys = returnGeneratedKeys;
}
}
三、填充占位符
ShardingPreparedStatement
的抽象父类AbstractShardingPreparedStatementAdapter
实现了填充占位符的功能。
public abstract class AbstractShardingPreparedStatementAdapter extends AbstractUnsupportedOperationPreparedStatement {
private final List<SetParameterMethodInvocation> setParameterMethodInvocations = new LinkedList<>();
@Getter
private final List<Object> parameters = new ArrayList<>();
@Override
public final void setLong(final int parameterIndex, final long x) {
setParameter(parameterIndex, x);
}
}
AbstractShardingPreparedStatementAdapter
的setXXX方法都是将参数保存到parameters这个列表中。
private void setParameter(final int parameterIndex, final Object value) {
if (parameters.size() == parameterIndex - 1) {
parameters.add(value);
return;
}
for (int i = parameters.size(); i <= parameterIndex - 1; i++) {
parameters.add(null);
}
parameters.set(parameterIndex - 1, value);
}
四、解析入口
执行SQL(preparedStatement.execute)是针对于用户而言的,实际上ShardingPrepareStatement
在这个阶段做了四个重要操作:解析、路由、重写、执行。
public final class ShardingPreparedStatement extends AbstractShardingPreparedStatementAdapter {
private final PreparedStatementExecutor preparedStatementExecutor;
@Override
public boolean execute() throws SQLException {
try {
// 资源清理
preparedStatementExecutor.clear();
// 解析 路由 重写
prepare();
// 初始化PreparedStatementExecutor
initPreparedStatementExecutor();
// 执行SQL
return preparedStatementExecutor.execute();
} finally {
// 资源清理
clearBatch();
}
}
}
1、资源清理
PreparedStatementExecutor
的抽象父类AbstractStatementExecutor
实现了clear方法,主要是清空各种集合。
@Getter
public abstract class AbstractStatementExecutor {
// 数据库连接集合
private final Collection<Connection> connections = new LinkedList<>();
// 参数列表集合 最外层的List下标与statements的下标对应
private final List<List<Object>> parameterSets = new LinkedList<>();
// Statement集合
private final List<Statement> statements = new LinkedList<>();
// ResultSet集合
private final List<ResultSet> resultSets = new CopyOnWriteArrayList<>();
// StatementExecuteUnit集合
private final Collection<InputGroup<StatementExecuteUnit>> inputGroups = new LinkedList<>();
public void clear() throws SQLException {
clearStatements(); // 关闭所有Statement
statements.clear();
parameterSets.clear();
connections.clear();
resultSets.clear();
inputGroups.clear();
}
private void clearStatements() throws SQLException {
for (Statement each : getStatements()) {
each.close();
}
}
}
2、BasePrepareEngine#prepare
public final class ShardingPreparedStatement extends AbstractShardingPreparedStatementAdapter {
private final String sql;
private final BasePrepareEngine prepareEngine;
private ExecutionContext executionContext;
private void prepare() {
// 解析 路由 重写
executionContext = prepareEngine.prepare(sql, getParameters());
// 从executionContext取出生成的主键ID放入generatedValues
findGeneratedKey().ifPresent(generatedKey -> generatedValues.add(generatedKey.getGeneratedValues().getLast()));
}
}
BasePrepareEngine
的prepare
方法包含解析、路由、重写三个核心逻辑。
public abstract class BasePrepareEngine {
public ExecutionContext prepare(final String sql, final List<Object> parameters) {
// 拷贝一份参数列表
List<Object> clonedParameters = cloneParameters(parameters);
// 解析 & 路由
RouteContext routeContext = executeRoute(sql, clonedParameters);
ExecutionContext result = new ExecutionContext(routeContext.getSqlStatementContext());
// 重写
result.getExecutionUnits().addAll(executeRewrite(sql, clonedParameters, routeContext));
// 打印SQL
if (properties.<Boolean>getValue(ConfigurationPropertyKey.SQL_SHOW)) {
SQLLogger.logSQL(sql, properties.<Boolean>getValue(ConfigurationPropertyKey.SQL_SIMPLE), result.getSqlStatementContext(), result.getExecutionUnits());
}
return result;
}
}
ExecutionContext 解析、路由、重写的产物就是ExecutionContext
,代表sql执行的上下文。
@RequiredArgsConstructor
@Getter
public class ExecutionContext {
private final SQLStatementContext sqlStatementContext;
private final Collection<ExecutionUnit> executionUnits = new LinkedHashSet<>();
}
SQLStatementContext
public interface SQLStatementContext<T extends SQLStatement> {
T getSqlStatement();
TablesContext getTablesContext();
}
SQLStatementContext
能获取SQLStatement
和TablesContext
。
例如SelectStatementContext
包括查询字段(ProjectionsContext
)、分组(GroupByContext
)、排序(OrderByContext
)、分页(PaginationContext
)、表(TablesContext
)等等。
@Getter
public final class SelectStatementContext extends CommonSQLStatementContext<SelectStatement> implements TableAvailable, WhereAvailable {
private final TablesContext tablesContext;
private final ProjectionsContext projectionsContext;
private final GroupByContext groupByContext;
private final OrderByContext orderByContext;
private final PaginationContext paginationContext;
private final boolean containsSubquery;
}
ExecutionUnit
ExecutionContext
执行上下文中包含多个ExecutionUnit
执行单元。
每个ExecutionUnit
执行单元对应某个dataSource(如demo_ds_1)的一个SQLUnit
SQL单元。
public final class ExecutionUnit {
private final String dataSourceName;
private final SQLUnit sqlUnit;
}
每个SQLUnit
SQL单元对应一个重写完成的sql(包含?占位符)和一个parameters参数列表。
public final class SQLUnit {
private final String sql;
private final List<Object> parameters;
}
3、BasePrepareEngine#executeRoute
BasePrepareEngine
的executeRoute
方法先将RouteDecorator
注册到DataNodeRouter
实例中,然后调用子类实现的route
方法。
public abstract class BasePrepareEngine {
private final Collection<BaseRule> rules中这个;
private final DataNodeRouter router;
private RouteContext executeRoute(final String sql, final List<Object> clonedParameters) {
// 向DataNodeRouter实例中注册BaseRule对应的RouteDecorator
registerRouteDecorator();
// 解析 & 路由 子类实现
return route(router, sql, clonedParameters);
}
private void registerRouteDecorator() {
// 循环所有通过SPI机制注册的RouteDecorator的实现类Class
for (Class<? extends RouteDecorator> each : OrderedRegistry.getRegisteredClasses(RouteDecorator.class)) {
// 反射实例化这个RouteDecorator 省略
RouteDecorator routeDecorator = createRouteDecorator(each);
// 获取这个RouteDecorator支持的BaseRule的Class
Class<?> ruleClass = (Class<?>) routeDecorator.getType();
// 过滤出Collection<BaseRule> rules中这个RouteDecorator支持的BaseRule实例
// 把这个BaseRule和routeDecorator的对应关系注册到DataNodeRouter
rules.stream().filter(rule -> rule.getClass() == ruleClass || rule.getClass().getSuperclass() == ruleClass).collect(Collectors.toList())
.forEach(rule -> router.registerDecorator(rule, routeDecorator));
}
}
protected abstract RouteContext route(DataNodeRouter dataNodeRouter, String sql, List<Object> parameters);
}
PreparedQueryPrepareEngine
对route
方法的实现,就是直接调用DataNodeRouter
的route
方法,第三个参数传true表示启用sql解析缓存。
public final class PreparedQueryPrepareEngine extends BasePrepareEngine {
@Override
protected RouteContext route(final DataNodeRouter dataNodeRouter, final String sql, final List<Object> parameters) {
return dataNodeRouter.route(sql, parameters, true);
}
}
DataNodeRouter
通过SQLParserEngine
解析SQLStatement
,通过RouteDecorator
路由。
public final class DataNodeRouter {
// 包含数据源和表结构信息
private final ShardingSphereMetaData metaData;
// 配置信息
private final ConfigurationProperties properties;
// SQL解析引擎
private final SQLParserEngine parserEngine;
// BaseRule-RouteDecorator映射关系,BasePrepareEngine注入
private final Map<BaseRule, RouteDecorator> decorators = new LinkedHashMap<>();
// SPI钩子 暴露给用户的扩展点
private SPIRoutingHook routingHook = new SPIRoutingHook();
public RouteContext route(final String sql, final List<Object> parameters, final boolean useCache) {
// 执行所有RoutingHook的start方法
routingHook.start(sql);
try {
// 解析 & 路由
RouteContext result = executeRoute(sql, parameters, useCache);
// 执行所有RoutingHook的finishSuccess方法
routingHook.finishSuccess(result, metaData.getSchema());
return result;
} catch (final Exception ex) {
// 执行所有RoutingHook的finishFailure方法
routingHook.finishFailure(ex);
throw ex;
}
}
private RouteContext executeRoute(final String sql, final List<Object> parameters, final boolean useCache) {
// 解析
RouteContext result = createRouteContext(sql, parameters, useCache);
// 路由
for (Entry<BaseRule, RouteDecorator> entry : decorators.entrySet()) {
result = entry.getValue().decorate(result, metaData, entry.getKey(), properties);
}
return result;
}
}
五、解析
解析是ShardingJDBC的第一步,主要是把字符串形式的sql语句,转换为对象形式的SQLStatement
。DataNodeRouter#createRouteContext
是解析SQL的入口,直接调用了SQLParserEngine
的parse
方法,对于PreparedQueryPrepareEngine
进入该方法,useCache=true
。
public final class DataNodeRouter {
// 包含数据源和表结构信息
private final ShardingSphereMetaData metaData;
// SQL解析引擎
private final SQLParserEngine parserEngine;
private RouteContext createRouteContext(final String sql, final List<Object> parameters, final boolean useCache) {
// 将sql解析为SQLStatement
SQLStatement sqlStatement = parserEngine.parse(sql, useCache);
try {
// 创建SQL上下文
SQLStatementContext sqlStatementContext = SQLStatementContextFactory.newInstance(metaData.getSchema(), sql, parameters, sqlStatement);
// 返回初始化的路由上下文
return new RouteContext(sqlStatementContext, parameters, new RouteResult());
} catch (final IndexOutOfBoundsException ex) {
return new RouteContext(new CommonSQLStatementContext(sqlStatement), parameters, new RouteResult());
}
}
}
SQLParserEngine
真正执行解析SQL,这个SQLParserEngine
正是之前在创建ShardingRuntimeContext
时构造的SQLParserEngine
。
public final class SQLParserEngine {
public SQLStatement parse(final String sql, final boolean useCache) {
ParsingHook parsingHook = new SPIParsingHook();
parsingHook.start(sql);
try {
// 执行解析
SQLStatement result = parse0(sql, useCache);
parsingHook.finishSuccess(result);
return result;
} catch (final Exception ex) {
parsingHook.finishFailure(ex);
throw ex;
}
}
}
和DataNodeRouter
的处理方式一样,SQLParserEngine
的公共方法parse
中执行了各种SPI钩子方法,最终是通过私有方法parse0
实际执行SQL解析。
@RequiredArgsConstructor
public final class SQLParserEngine {
// 数据库类型名称 例如MySQL
private final String databaseTypeName;
// 缓存sql - SQLStatement
private final SQLParseResultCache cache = new SQLParseResultCache();
private SQLStatement parse0(final String sql, final boolean useCache) {
// 尝试从缓存中获取解析的SQLStatement
if (useCache) {
Optional<SQLStatement> cachedSQLStatement = cache.getSQLStatement(sql);
if (cachedSQLStatement.isPresent()) {
return cachedSQLStatement.get();
}
}
// 构建ParseTree
ParseTree parseTree = new SQLParserExecutor(databaseTypeName, sql).execute().getRootNode();
// 构建SQLStatement
SQLStatement result = (SQLStatement) ParseTreeVisitorFactory.newInstance(databaseTypeName, VisitorRule.valueOf(parseTree.getClass())).visit(parseTree);
// 放入缓存
if (useCache) {
cache.put(sql, result);
}
return result;
}
}
首先对于PrepareStatement
,SQLParserEngine
会尝试从SQLParseResultCache
缓存中获取解析结果,这个SQLParseResultCache
使用的是guava的com.google.common.cache.Cache
。
public final class SQLParseResultCache {
private final Cache<String, SQLStatement> cache = CacheBuilder.newBuilder().softValues()
.initialCapacity(2000).maximumSize(65535).build();
}
接着两行代码,利用antlr
(Another Tool for Language Recognition)做词法解析和语法解析,把sql转换为SQLStatement
。我把两行代码中间的嵌套方法调用展开就是这样的。
// 1. 创建SQLParserExecutor
SQLParserExecutor sqlParserExecutor = new SQLParserExecutor(databaseTypeName, sql);
// 2. 根据不同的数据库类型(例如MySQLStatementParser#execute)创建解析树
ParseASTNode astNode = sqlParserExecutor.execute();
ParseTree parseTree = astNode.getRootNode();
// 3. 通过不同的数据库类型创建org.antlr.v4.runtime.tree.ParseTreeVisitor
ParseTreeVisitor parseTreeVisitor = ParseTreeVisitorFactory.newInstance(databaseTypeName, VisitorRule.valueOf(parseTree.getClass()));
// 4. 执行visit方法,最终将解析树转换为SQLStatement
SQLStatement result = (SQLStatement) parseTreeVisitor.visit(parseTree);
SelectStatement
的结构是这样的。
public final class SelectStatement extends DMLStatement {
// 字段
private ProjectionsSegment projections;
// 表
private final Collection<TableReferenceSegment> tableReferences = new LinkedList<>();
// where
private WhereSegment where;
// groupBy
private GroupBySegment groupBy;
// orderBy
private OrderBySegment orderBy;
// limit
private LimitSegment limit;
// 父statement
private SelectStatement parentStatement;
// lock
private LockSegment lock;
}
回到DataNodeRouter#createRouteContext
,通过SQLStatementContextFactory
工厂创建SQLStatementContext
。
SQLStatementContext sqlStatementContext = SQLStatementContextFactory.newInstance(metaData.getSchema(), sql, parameters, sqlStatement);
SQLStatementContextFactory
先是一段if-else根据SQL类型区分。
public final class SQLStatementContextFactory {
public static SQLStatementContext newInstance(final SchemaMetaData schemaMetaData, final String sql, final List<Object> parameters, final SQLStatement sqlStatement) {
if (sqlStatement instanceof DMLStatement) {
return getDMLStatementContext(schemaMetaData, sql, parameters, (DMLStatement) sqlStatement);
}
if (sqlStatement instanceof DDLStatement) {
return getDDLStatementContext((DDLStatement) sqlStatement);
}
if (sqlStatement instanceof DCLStatement) {
return getDCLStatementContext((DCLStatement) sqlStatement);
}
if (sqlStatement instanceof DALStatement) {
return getDALStatementContext((DALStatement) sqlStatement);
}
return new CommonSQLStatementContext(sqlStatement);
}
}
对于DMLStatement
又是一段if-else根据SQL类型区分调用哪个构造方法。
private static SQLStatementContext getDMLStatementContext(final SchemaMetaData schemaMetaData, final String sql, final List<Object> parameters, final DMLStatement sqlStatement) {
if (sqlStatement instanceof SelectStatement) {
return new SelectStatementContext(schemaMetaData, sql, parameters, (SelectStatement) sqlStatement);
}
if (sqlStatement instanceof UpdateStatement) {
return new UpdateStatementContext((UpdateStatement) sqlStatement);
}
if (sqlStatement instanceof DeleteStatement) {
return new DeleteStatementContext((DeleteStatement) sqlStatement);
}
if (sqlStatement instanceof InsertStatement) {
return new InsertStatementContext(schemaMetaData, parameters, (InsertStatement) sqlStatement);
}
throw new UnsupportedOperationException(String.format("Unsupported SQL statement `%s`", sqlStatement.getClass().getSimpleName()));
}
}
SelectStatementContext
的构造方法就是解析SelectStatement
里的属性,构造为上下文,不细看。
@Getter
@ToString(callSuper = true)
public final class SelectStatementContext extends CommonSQLStatementContext<SelectStatement> implements TableAvailable, WhereAvailable {
// 表
private final TablesContext tablesContext;
// 字段
private final ProjectionsContext projectionsContext;
// groupBy
private final GroupByContext groupByContext;
// orderBy
private final OrderByContext orderByContext;
// 分页
private final PaginationContext paginationContext;
// 是否包含子查询
private final boolean containsSubquery;
public SelectStatementContext(final SchemaMetaData schemaMetaData, final String sql, final List<Object> parameters, final SelectStatement sqlStatement) {
super(sqlStatement);
tablesContext = new TablesContext(sqlStatement.getSimpleTableSegments());
groupByContext = new GroupByContextEngine().createGroupByContext(sqlStatement);
orderByContext = new OrderByContextEngine().createOrderBy(sqlStatement, groupByContext);
projectionsContext = new ProjectionsContextEngine(schemaMetaData).createProjectionsContext(sql, sqlStatement, groupByContext, orderByContext);
paginationContext = new PaginationContextEngine().createPaginationContext(sqlStatement, projectionsContext, parameters);
// 这里写着FIXME 写死了返回false
containsSubquery = containsSubquery();
}
}
总结
- 对于
dataSource.getConnection
,ShardingDataSource创建的Connection实现类是ShardingConnection,它持有数据源Map和分片运行时上下文。 - 对于
connection.prepareStatement
,ShardingConnection创建的PrepareStatement实现类是ShardingPrepareStatement,execute方法执行了四个关键操作,即解析、路由、重写、执行。 - SQLParserEngine的parse0方法是sql解析的核心逻辑,利用
antlr
(Another Tool for Language Recognition)做词法解析和语法解析,把sql转换为SQLStatement
。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13064.html