结果获取
@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
扫描二维码关注公众号,回复:
2800254 查看本文章
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结果归并器,加上面的四种,总共有五种,下面将会一一介绍