前面几篇文章介绍了SQL解析,SQL路由,SQL改写的过程,包括组装成最后的Collection<PreparedStatementUnit>
这篇文章就开始介绍SQL的执行了
public boolean execute() throws SQLException {
try {
① Collection<PreparedStatementUnit> preparedStatementUnits = route();
② return new PreparedStatementExecutor(
getConnection().getShardingContext().getExecutorEngine(), routeResult.getSqlStatement().getType(), preparedStatementUnits, getParameters()).execute();
} finally {
clearBatch();
}
}
①也就是我们之前文章介绍的过程
下面我们重点介绍②,我们看到这里其实分为两步:
1.生成PreparedStatementExecutor对象,也就是执行sql的对象
2.调用PreparedStatementExecutor的execute, executeUpdate, executeQuery 方法,进行SQL的执行
这里我们主要以execute方法进行详细展开
public boolean execute() throws SQLException {
List<Boolean> result = executorEngine.executePreparedStatement(sqlType, preparedStatementUnits, parameters, new ExecuteCallback<Boolean>() {
@Override
public Boolean execute(final BaseStatementUnit baseStatementUnit) throws Exception {
return ((PreparedStatement) baseStatementUnit.getStatement()).execute();
}
});
if (null == result || result.isEmpty() || null == result.get(0)) {
return false;
}
return result.get(0);
}
在方法中我们看到,其实最终调用的是executorEngine.executePreparedStatement方法,而在这个方法上我们看到,最后一个参数传递的是一个回调对象,其中的主要方法调用的是PreparedStatement的execute方法,这个大家应该都很熟悉了,是底层SQL的执行方法。
我们对executorEngine.executePreparedStatement进行展开
public <T> List<T> executePreparedStatement(
final SQLType sqlType, final Collection<PreparedStatementUnit> preparedStatementUnits, final List<Object> parameters, final ExecuteCallback<T> executeCallback) throws SQLException {
return execute(sqlType, preparedStatementUnits, Collections.singletonList(parameters), executeCallback);
}
private <T> List<T> execute(
final SQLType sqlType, final Collection<? extends BaseStatementUnit> baseStatementUnits,
final List<List<Object>> parameterSets, final ExecuteCallback<T> executeCallback) throws SQLException {
if (baseStatementUnits.isEmpty()) {
return Collections.emptyList();
}
OverallExecutionEvent event = new OverallExecutionEvent(sqlType, baseStatementUnits.size());
EventBusInstance.getInstance().post(event);
Iterator<? extends BaseStatementUnit> iterator = baseStatementUnits.iterator();
① BaseStatementUnit firstInput = iterator.next();
② ListenableFuture<List<T>> restFutures = asyncExecute(sqlType, Lists.newArrayList(iterator), parameterSets, executeCallback);
T firstOutput;
List<T> restOutputs;
try {
③ firstOutput = syncExecute(sqlType, firstInput, parameterSets, executeCallback);
④ restOutputs = restFutures.get();
//CHECKSTYLE:OFF
} catch (final Exception ex) {
//CHECKSTYLE:ON
event.setException(ex);
event.setEventExecutionType(EventExecutionType.EXECUTE_FAILURE);
EventBusInstance.getInstance().post(event);
ExecutorExceptionHandler.handleException(ex);
return null;
}
event.setEventExecutionType(EventExecutionType.EXECUTE_SUCCESS);
EventBusInstance.getInstance().post(event);
⑤ List<T> result = Lists.newLinkedList(restOutputs);
result.add(0, firstOutput);
return result;
}
最终调用的是内部的execute方法,这里我们分步奏进行详细解析
1.获取到第一个BaseStatementUnit 即PreparedStatementUnit
2.异步执行后面的所有BaseStatementUnit
3.同步执行第一个BaseStatementUnit
4.获取第二步异步执行的结果(阻塞获取)
5.组合第四步和第3步获取的结果LIST
在这里我们主要看第2,和3两步的执行过程
首先看第三步的同步方法
private <T> T syncExecute(final SQLType sqlType, final BaseStatementUnit baseStatementUnit, final List<List<Object>> parameterSets, final ExecuteCallback<T> executeCallback) throws Exception {
return executeInternal(sqlType, baseStatementUnit, parameterSets, executeCallback, ExecutorExceptionHandler.isExceptionThrown(), ExecutorDataMap.getDataMap());
}
private <T> T executeInternal(final SQLType sqlType, final BaseStatementUnit baseStatementUnit, final List<List<Object>> parameterSets, final ExecuteCallback<T> executeCallback,
final boolean isExceptionThrown, final Map<String, Object> dataMap) throws Exception {
synchronized (baseStatementUnit.getStatement().getConnection()) {
T result;
ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown);
ExecutorDataMap.setDataMap(dataMap);
List<AbstractExecutionEvent> events = new LinkedList<>();
if (parameterSets.isEmpty()) {
events.add(getExecutionEvent(sqlType, baseStatementUnit, Collections.emptyList()));
}
for (List<Object> each : parameterSets) {
events.add(getExecutionEvent(sqlType, baseStatementUnit, each));
}
for (AbstractExecutionEvent event : events) {
② EventBusInstance.getInstance().post(event);
}
try {
① result = executeCallback.execute(baseStatementUnit);
} catch (final SQLException ex) {
for (AbstractExecutionEvent each : events) {
each.setEventExecutionType(EventExecutionType.EXECUTE_FAILURE);
each.setException(ex);
③ EventBusInstance.getInstance().post(each);
ExecutorExceptionHandler.handleException(ex);
}
return null;
}
for (AbstractExecutionEvent each : events) {
each.setEventExecutionType(EventExecutionType.EXECUTE_SUCCESS);
④ EventBusInstance.getInstance().post(each);
}
return result;
}
最终调用的是executeInternal方法,在这个方法里面我们看到最终真正跟数据库有交互的是调用了我们传过来的回调类,在①这里有标注,这里就是我们类中的方法,PreparedStatement的execute方法。
在这里有一个特殊的处理,大家可以看到标注②③④的位置,在SQL的执行前,执行成功,执行失败,都会通过eventBus进行post。并且在执行失败的时候,抛出相应的异常。
接下来看一下第二步异步执行的过程:
private <T> ListenableFuture<List<T>> asyncExecute(
final SQLType sqlType, final Collection<BaseStatementUnit> baseStatementUnits, final List<List<Object>> parameterSets, final ExecuteCallback<T> executeCallback) {
List<ListenableFuture<T>> result = new ArrayList<>(baseStatementUnits.size());
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
final Map<String, Object> dataMap = ExecutorDataMap.getDataMap();
for (final BaseStatementUnit each : baseStatementUnits) {
result.add(executorService.submit(new Callable<T>() {
@Override
public T call() throws Exception {
return executeInternal(sqlType, each, parameterSets, executeCallback, isExceptionThrown, dataMap);
}
}));
}
return Futures.allAsList(result);
}
这里主要是循环多线程调用executeInternal方法,这里跟同步调用的方法是一样的,就不在贴代码了。
并且在大方法中,会捕获到2,3步执行的异常,如果有异常会给eventBus发送失败消息,成功的话发送成功消息。
这里的eventBus主要是后续可对失败进行重试的。