sharding-jdbc系列之结果归并(七)

 

结果获取

@Override
    public ResultSet getResultSet() throws SQLException {
          // 当前的执行结果不为空,则直接返回
        if (null != currentResultSet) {
            return currentResultSet;
        }    
       // 单表执行,通过SQL路由之后,只有一个PreparedStatement执行,则无需进行结果归并,直接返回结果
        if (1 == routedStatements.size()) {
            currentResultSet = routedStatements.iterator().next().getResultSet();
            return currentResultSet;
        }
          // 获取routedStatements中PreparedStatement的resultSet()
        List<ResultSet> resultSets = new ArrayList<>(routedStatements.size());
        for (PreparedStatement each : routedStatements) {
            resultSets.add(each.getResultSet());
        }
          // 结果合并
        currentResultSet = new ShardingResultSet(resultSets, new MergeEngine(resultSets, (SelectStatement) routeResult.getSqlStatement()).merge());
        return currentResultSet;
}

结合上文,调用玩execute()方法,将SQL执行完成之后,程序会继续调用getResultSet()方法用来获取执行结果

步骤说明:

1.判断当前的执行结果是否为空,不为空则直接返回

2.判断是否是单表执行,如果是单表执行,则无需进行结果归并,直接返回结果

3.收集routedStatements中的PreparedStatement的执行结果

3.调用归并引擎进行结果归并,调用merge()方法

MergeEngine

public MergeEngine(final List<ResultSet> resultSets, final SelectStatement selectStatement) throws SQLException {
        this.resultSets = resultSets;
        this.selectStatement = selectStatement;
          // 从所有的结果集中,取出其中一个来,获取列名对应的列的坐标。
        columnLabelIndexMap = getColumnLabelIndexMap(resultSets.get(0));
 }

private Map<String, Integer> getColumnLabelIndexMap(final ResultSet resultSet) throws SQLException {
          // 获取ResultSet中的meta数据
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        Map<String, Integer> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
          // 根据列的数量,循环。
        for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
              // key = 列名  ,value = 列的坐标
            result.put(SQLUtil.getExactlyValue(resultSetMetaData.getColumnLabel(i)), i);
        }
        return result;
}

merge方法

public ResultSetMerger merge() throws SQLException {
          // 设置列的坐标信息
        selectStatement.setIndexForItems(columnLabelIndexMap);
          // 调用build()方法
        return decorate(build());
}

步骤说明:

1.设置列的坐标信息
2.调用build方法,判断SQL的条件,比如 分组,排序之类的,调用不同的结果归并

private ResultSetMerger build() throws SQLException {
          // SQL中 分组字段不为空 或者  聚合计算不为空 (avg计算会被转化为sum,count)
        if (!selectStatement.getGroupByItems().isEmpty() || !selectStatement.getAggregationSelectItems().isEmpty()) {
              // 分组和排序的字段一致
            if (selectStatement.isSameGroupByAndOrderByItems()) {
                return new GroupByStreamResultSetMerger(columnLabelIndexMap, resultSets, selectStatement);
            } else {
                  // 单独走分组的
                return new GroupByMemoryResultSetMerger(columnLabelIndexMap, resultSets, selectStatement);
            }
        }
          // 排序字段不为空
        if (!selectStatement.getOrderByItems().isEmpty()) {
            return new OrderByStreamResultSetMerger(resultSets, selectStatement.getOrderByItems());
        }
          // 默认
        return new IteratorStreamResultSetMerger(resultSets);
}

根据这段代码可知,其作用是根据sql语句选择多个不同的ResultSetMerger对结果进行合并处理,

上面体现的代码ResultSetMerger实现有GroupByStreamResultSetMerger,GroupByMemoryResultSetMerger,OrderByStreamResultSetMerger,IteratorStreamResultSetMerger

decorate方法

private ResultSetMerger decorate(final ResultSetMerger resultSetMerger) throws SQLException {
        ResultSetMerger result = resultSetMerger;
          // 是否需要分页
        if (null != selectStatement.getLimit()) {
              // 调用分页结果合并器处理
            result = new LimitDecoratorResultSetMerger(result, selectStatement.getLimit());
        }
        return result;
    }

decorate方法主要是针对分页进行结果归并处理,这里又多了一个

LimitDecoratorResultSetMerger结果归并器,加上面的四种,总共有五种,下面将会一一介绍

猜你喜欢

转载自blog.csdn.net/u012394095/article/details/81531524