Skip to content

Commit

Permalink
feat- 上周源码注释
Browse files Browse the repository at this point in the history
  • Loading branch information
marvin9551 committed Jul 29, 2024
1 parent 22f2034 commit 25563a9
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 7 deletions.
73 changes: 69 additions & 4 deletions src/main/java/org/apache/ibatis/executor/BaseExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,34 @@
public abstract class BaseExecutor implements Executor {

private static final Log log = LogFactory.getLog(BaseExecutor.class);

/**
* 事务对象
*/
protected Transaction transaction;
/**
* 包装的 Executor 对象
*/
protected Executor wrapper;

/**
* 延迟加载队列
*/
protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
/**
* 本地缓存,即一级缓存
*/
protected PerpetualCache localCache;
/**
* 本地输出类型的参数的缓存
*/
protected PerpetualCache localOutputParameterCache;
protected Configuration configuration;

/**
* 记录嵌套查询的层级
*/
protected int queryStack;
/**
* 是否关闭
*/
private boolean closed;

protected BaseExecutor(Configuration configuration, Transaction transaction) {
Expand All @@ -74,26 +92,31 @@ protected BaseExecutor(Configuration configuration, Transaction transaction) {

@Override
public Transaction getTransaction() {
// 如果关闭,返回ExecutorException 异常
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 返回事务
return transaction;
}

@Override
public void close(boolean forceRollback) {
try {
try {
// 回滚事务
rollback(forceRollback);
} finally {
if (transaction != null) {
// 关闭事务
transaction.close();
}
}
} catch (SQLException e) {
// Ignore. There's nothing that can be done at this point.
log.warn("Unexpected exception on closing transaction. Cause: " + e);
} finally {
// 置空变量
transaction = null;
deferredLoads = null;
localCache = null;
Expand All @@ -110,10 +133,13 @@ public boolean isClosed() {
@Override
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
// 如果关闭,抛出ExecutorException 异常
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 清空本地缓存
clearLocalCache();
// 执行写操作
return doUpdate(ms, parameter);
}

Expand All @@ -123,17 +149,22 @@ public List<BatchResult> flushStatements() throws SQLException {
}

public List<BatchResult> flushStatements(boolean isRollBack) throws SQLException {
// 如果已经关闭,抛出ExecutorException 异常
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 执行刷入批处理语句
return doFlushStatements(isRollBack);
}

@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler)
throws SQLException {
// 创建 BoundSql 对象
BoundSql boundSql = ms.getBoundSql(parameter);
// 创建 CacheKey 对象
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
// 查询
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}

Expand All @@ -142,30 +173,42 @@ public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBoun
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler,
CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
// 已经关闭 则抛出 ExecutorException 异常
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 如果查询层级为0 并且要求刷新本地缓存 则清空本地缓存
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
// queryStack 自增
queryStack++;
// 根据 CacheKey 从查询缓存中获取缓存数据
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
// 如果缓存数据不为空
if (list != null) {
// 处理从缓存中获取的到数据
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
// 从数据库进行查询
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
// 查询层级自减
queryStack--;
}
// 如果查询层级为0
if (queryStack == 0) {
// 执行延迟加载
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// 清空 deferredLoads
// issue #601
deferredLoads.clear();
// 如果缓存级别是 LocalCacheScope.STATEMENT ,则进行清理
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
Expand All @@ -176,7 +219,9 @@ public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBoun

@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
// 获得 BoundSql 对象
BoundSql boundSql = ms.getBoundSql(parameter);
// 执行查询
return doQueryCursor(ms, parameter, rowBounds, boundSql);
}

Expand All @@ -199,14 +244,17 @@ public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBo
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 创建 CacheKey 对象
CacheKey cacheKey = new CacheKey();
// 设置 id、offset、limit、sql 到 CacheKey 对象中
cacheKey.update(ms.getId());
cacheKey.update(rowBounds.getOffset());
cacheKey.update(rowBounds.getLimit());
cacheKey.update(boundSql.getSql());
// 设置 ParameterMapping 数组的元素对应的每个 value 到 CacheKey 对象中
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
// mimic DefaultParameterHandler logic 这块逻辑,和 DefaultParameterHandler 获取 value 是一致的。
MetaObject metaObject = null;
for (ParameterMapping parameterMapping : parameterMappings) {
if (parameterMapping.getMode() != ParameterMode.OUT) {
Expand All @@ -227,6 +275,7 @@ public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBo
cacheKey.update(value);
}
}
// 设置 Environment.id 到 CacheKey 对象中
if (configuration.getEnvironment() != null) {
// issue #176
cacheKey.update(configuration.getEnvironment().getId());
Expand All @@ -241,11 +290,15 @@ public boolean isCached(MappedStatement ms, CacheKey key) {

@Override
public void commit(boolean required) throws SQLException {
// 如果关闭,抛出 ExecutorException 异常
if (closed) {
throw new ExecutorException("Cannot commit, transaction is already closed");
}
// 清空本地缓存
clearLocalCache();
// 刷入批处理语句
flushStatements();
// 是否需要提交事务?需要则提交事务
if (required) {
transaction.commit();
}
Expand All @@ -255,20 +308,28 @@ public void commit(boolean required) throws SQLException {
public void rollback(boolean required) throws SQLException {
if (!closed) {
try {
// 清空本地缓存
clearLocalCache();
// 刷入批处理语句
flushStatements(true);
} finally {
// 判断是否需要回滚,如果需要,则执行回滚操作
if (required) {
transaction.rollback();
}
}
}
}

/**
* 清除本地缓存
*/
@Override
public void clearLocalCache() {
if (!closed) {
// 清理localCache
localCache.clear();
// 清理localOutputParameterCache
localOutputParameterCache.clear();
}
}
Expand Down Expand Up @@ -331,12 +392,16 @@ private void handleLocallyCachedOutputParameters(MappedStatement ms, CacheKey ke
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds,
ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
// 在缓存中,添加占位符
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
// 执行读操作
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
// 移除 占位符
localCache.removeObject(key);
}
// 添加到缓存中
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
Expand Down
37 changes: 36 additions & 1 deletion src/main/java/org/apache/ibatis/executor/BatchExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,21 @@
public class BatchExecutor extends BaseExecutor {

public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;

/**
* statement 数组
*/
private final List<Statement> statementList = new ArrayList<>();
/**
* BatchResult 数组
*/
private final List<BatchResult> batchResultList = new ArrayList<>();
/**
* 当前SQL
*/
private String currentSql;
/**
* 当前 MappedStatement 对象
*/
private MappedStatement currentStatement;

public BatchExecutor(Configuration configuration, Transaction transaction) {
Expand All @@ -54,27 +65,41 @@ public BatchExecutor(Configuration configuration, Transaction transaction) {
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
final Configuration configuration = ms.getConfiguration();
// 创建 statementHandler 对象
final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT,
null, null);
final BoundSql boundSql = handler.getBoundSql();
final String sql = boundSql.getSql();
final Statement stmt;
// 如果匹配最后一次 currentSql 和 currentStatement,则聚合到 BatchResult 中
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
// 获得最后一次statement 对象
int last = statementList.size() - 1;
stmt = statementList.get(last);
// 设置事务超时时间
applyTransactionTimeout(stmt);
// 设置 SQL 上的参数,例如 PrepareStatement 对象上的占位符
handler.parameterize(stmt);// fix Issues 322
// 获得最后一次的 BatchResult 对象,并添加参数到其中
BatchResult batchResult = batchResultList.get(last);
batchResult.addParameterObject(parameterObject);
// 如果不匹配最后一次 currentSql 和 currentStatement ,则新建 BatchResult 对象
} else {
// 获得 Connection
Connection connection = getConnection(ms.getStatementLog());
// 创建 Statement 或 PrepareStatement 对象
stmt = handler.prepare(connection, transaction.getTimeout());
// 设置 SQL 上的参数,例如 PrepareStatement 对象上的占位符
handler.parameterize(stmt); // fix Issues 322
// 重新设置 currentSql 和 currentStatement
currentSql = sql;
currentStatement = ms;
// 添加 Statement 到 statementList 中
statementList.add(stmt);
// 创建 BatchResult 对象,并添加到 batchResultList 中
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
// 批处理
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
Expand Down Expand Up @@ -115,15 +140,20 @@ protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowB
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
try {
List<BatchResult> results = new ArrayList<>();
// 如果isRollback 为true,返回空数组
if (isRollback) {
return Collections.emptyList();
}
// 遍历 statementList 和 batchResultList 数组,逐个提交批处理
for (int i = 0, n = statementList.size(); i < n; i++) {
// 获得 Statement 和 BatchResult 对象
Statement stmt = statementList.get(i);
applyTransactionTimeout(stmt);
BatchResult batchResult = batchResultList.get(i);
try {
// 批量执行
batchResult.setUpdateCounts(stmt.executeBatch());
// 处理主键生成
MappedStatement ms = batchResult.getMappedStatement();
List<Object> parameterObjects = batchResult.getParameterObjects();
KeyGenerator keyGenerator = ms.getKeyGenerator();
Expand All @@ -136,8 +166,10 @@ public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLExcepti
}
}
// Close statement to close cursor #1109
// 关闭 Statement 对象
closeStatement(stmt);
} catch (BatchUpdateException e) {
// 如果发生异常,则抛出 BatchExecutorException 异常
StringBuilder message = new StringBuilder();
message.append(batchResult.getMappedStatement().getId()).append(" (batch index #").append(i + 1).append(")")
.append(" failed.");
Expand All @@ -147,13 +179,16 @@ public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLExcepti
}
throw new BatchExecutorException(message.toString(), e, results, batchResult);
}
// 添加到结果集
results.add(batchResult);
}
return results;
} finally {
// 关闭 Statement 们
for (Statement stmt : statementList) {
closeStatement(stmt);
}
// 置空 currentSql、statementList、batchResultList 属性
currentSql = null;
statementList.clear();
batchResultList.clear();
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/org/apache/ibatis/executor/BatchResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,25 @@
* @author Jeff Butler
*/
public class BatchResult {

/**
* MappedStatement 对象
*/
private final MappedStatement mappedStatement;
/**
* SQL
*/
private final String sql;
/**
* 参数对象集合
*
* 每一个元素,对应一次操作的参数
*/
private final List<Object> parameterObjects;

/**
* 更新数量集合
*
* 每一个元素,对应一次操作的更新数量
*/
private int[] updateCounts;

public BatchResult(MappedStatement mappedStatement, String sql) {
Expand Down
Loading

0 comments on commit 25563a9

Please sign in to comment.