collection嵌套collection sql不执行_ShardingJDBC源码阅读(七)执行

56202c373c49d77de591118707969454.png

前言

0fa6a4dd0377d72a27e8ae0c2b16b2d9.png本章分析ShardingJDBC的核心步骤:执行。

思考几个问题:

  • 执行一个逻辑SQL需要几个数据库连接?
  • 同一个逻辑SQL的多个实际SQL是并行执行还是串行执行?

一、初始化PreparedStatementExecutor

回到ShardingPreparedStatement的execute方法。

@Override
public boolean execute() throws SQLException {
    try {
        // 资源清理
        clearPrevious();
        // 解析 路由 重写
        prepare();
        // 初始化PreparedStatementExecutor
        initPreparedStatementExecutor();
        // 执行SQL
        return preparedStatementExecutor.execute();
    } finally {
        // 资源清理
        clearBatch();
    }
}

ShardingPreparedStatement#initPreparedStatementExecutor创建Connection和Statement。

private void initPreparedStatementExecutor() throws SQLException {
    
    // 创建连接 创建statement
    preparedStatementExecutor.init(executionContext);
    // 为statement设置参数
    setParametersForStatements();
    // 重放statement其他的反射调用
    replayMethodForStatements();
}

1、SQL分组&创建连接、statement

PreparedStatementExecutor#init

public void init(final ExecutionContext executionContext) throws SQLException {
    
    // 设置成员变量SQLStatementContext
    setSqlStatementContext(executionContext.getSqlStatementContext());
    // 获取连接 获取statement 转换为StatementExecuteUnit 放入成员变量inputGroups
    Collection executionUnits = executionContext.getExecutionUnits();
    Collection> inputGroups = obtainExecuteGroups(executionUnits);
    getInputGroups().addAll(inputGroups);// 把成员变量inputGroups 转换为 statement集合与参数列表集合 省略
    cacheStatements();
}

PreparedStatementExecutor#obtainExecuteGroups,调用SQLExecutePrepareTemplate的getExecuteUnitGroups,创建执行分组,这里把创建数据库连接和创建Statement的回调方法作为第二个参数传入。

private Collection> obtainExecuteGroups(final Collection executionUnits) throws SQLException {
    return getSqlExecutePrepareTemplate().getExecuteUnitGroups(executionUnits, new SQLExecutePrepareCallback() {
    // 创建数据库连接的回调方法@Overridepublic List getConnections(final ConnectionMode connectionMode, final String dataSourceName, final int connectionSize) throws SQLException {
    return PreparedStatementExecutor.super.getConnection().getConnections(connectionMode, dataSourceName, connectionSize);
      }// 创建PreparedStatement的回调方法@Overridepublic StatementExecuteUnit createStatementExecuteUnit(final Connection connection, final ExecutionUnit executionUnit, final ConnectionMode connectionMode) throws SQLException {
          PreparedStatement preparedStatement = createPreparedStatement(connection, executionUnit.getSqlUnit().getSql());return new StatementExecuteUnit(executionUnit, preparedStatement, connectionMode);
      }
  });
}

这里InputGroup只是封装了List而已。

public final class InputGroup<T> {
    
    private final List inputs;
}

SQLExecutePrepareTemplate#getExecuteUnitGroups是SQLExecutePrepareTemplate暴露的唯一公共方法,作用就是对sql分组,获取数据库连接创建Statement。

getSQLUnitGroups首先对ExecutionUnit按照dataSource分组。

public Collection> getExecuteUnitGroups(final Collection executionUnits, final SQLExecutePrepareCallback callback) throws SQLException {
    return getSynchronizedExecuteUnitGroups(executionUnits, callback);
}private Collection> getSynchronizedExecuteUnitGroups(final Collection executionUnits, final SQLExecutePrepareCallback callback) throws SQLException { // 按照ds分组
  Map> sqlUnitGroups = getSQLUnitGroups(executionUnits);
  Collection> result = new LinkedList<>();for (Entry> entry : sqlUnitGroups.entrySet()) { // 一个关键的方法
      List> sqlExecuteGroups = getSQLExecuteGroups(entry.getKey(), entry.getValue(), callback);
      result.addAll(sqlExecuteGroups);
  }return result;
}

关键方法getSQLExecuteGroups对同一ds中的sql再次分组,创建Connection并创建Statement。

@RequiredArgsConstructor
public final class SQLExecutePrepareTemplate {
  // 配置 max.connections.size.per.query 默认为1
  private final int maxConnectionsSizePerQuery;
  private List> getSQLExecuteGroups(final String dataSourceName, final List sqlUnits, final SQLExecutePrepareCallback callback) throws SQLException {
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值