DefaultSqlSession第三讲-事务提交,回滚,关闭SqlSession,清除缓存

本文介绍了DefaultSqlSession的commit、rollback、clearCache和close方法。事务的提交与回滚基于transaction,而transaction依赖于数据库。清除缓存则会清空执行器的本地缓存,关闭SqlSession通过执行器关闭statement。
上面两篇讲过query和update及flushStatements,这篇我们讲一下commit,rollback,clearCache,close
public class DefaultSqlSession
implements SqlSession
{
private Configuration configuration;
private Executor executor;
private boolean dirty;
public DefaultSqlSession(Configuration configuration, Executor executor)
{
this.configuration = configuration;
this.executor = executor;
dirty = false;
}
//查询
public Object selectOne(String statement)
{
return selectOne(statement, null);
}
public Object selectOne(String statement, Object parameter)
{
List list = selectList(statement, parameter);
if(list.size() == 1)
return list.get(0);
if(list.size() > 1)
throw new TooManyResultsException((new StringBuilder()).append("Expected one result (or null) to be returned by selectOne(), but found: ").append(list.size()).toString());
else
return null;
}
public List selectList(String statement)
{
return selectList(statement, null);
}

public List selectList(String statement, Object parameter)
{
return selectList(statement, parameter, RowBounds.DEFAULT);
}
public List selectList(String statement, Object parameter, RowBounds rowBounds)
{
List list;
try
{
org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
//调用executor的查询方法
List result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
list = result;
}
}
//插入
public int insert(String statement)
{
return insert(statement, null);
}

public int insert(String statement, Object parameter)
{
//委托给update方法
return update(statement, parameter);
}

public int update(String statement)
{
return update(statement, null);
}

public int update(String statement, Object parameter)
{
int i;
try
{
dirty = true;
org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
//委托给executor的update
i = executor.update(ms, wrapCollection(parameter));
}
}
//删除
public int delete(String statement)
{
//委托给update
return update(statement, null);
}

public int delete(String statement, Object parameter)
{
return update(statement, parameter);
}
//提交
public void commit()
{
commit(false);
}

public void commit(boolean force)
{
try
{
//委托executor的commit
executor.commit(isCommitOrRollbackRequired(force));
dirty = false;
}
}
//回滚
public void rollback()
{
rollback(false);
}

public void rollback(boolean force)
{
try
{
//委托executor的rollback
executor.rollback(isCommitOrRollbackRequired(force));
dirty = false;
}
}
//清除缓存
public void clearCache()
{
////委托executor的clearLocalCache
executor.clearLocalCache();
}
//刷新Statements
public List flushStatements()
{
List list;
try
{
//委托executor的flushStatements
list = executor.flushStatements();
}
}
//关闭SqlSession
public void close()
{
//委托executor的close
executor.close(isCommitOrRollbackRequired(false));
dirty = false;
}
}

DefaultSqlSession的commit,rollback,clearCache,close方法,实际是调用
Executor的方法,所有这些方法在BaseExecutor中
public abstract class BaseExecutor
implements Executor
{
private static final Log log = LogFactory.getLog(org/apache/ibatis/executor/BaseExecutor);
protected Transaction transaction;
protected ConcurrentLinkedQueue deferredLoads;
protected PerpetualCache localCache;
protected PerpetualCache localOutputParameterCache;
protected Configuration configuration;
protected int queryStack;
private boolean closed;
//提交事务
public void commit(boolean required)
throws SQLException
{
if(closed)
throw new ExecutorException("Cannot commit, transaction is already closed");
clearLocalCache();
flushStatements();
if(required)
transaction.commit();
}
//回滚事务
public void rollback(boolean required)
throws SQLException
{
if(closed)
break MISSING_BLOCK_LABEL_49;
clearLocalCache();
flushStatements(true);
if(required)
transaction.rollback();
break MISSING_BLOCK_LABEL_49;
Exception exception;
exception;
if(required)
transaction.rollback();
throw exception;
}
//清除本地缓存
public void clearLocalCache()
{
if(!closed)
{
localCache.clear();
localOutputParameterCache.clear();
}
}
//关闭statement
protected void closeStatement(Statement statement)
{
if(statement != null)
try
{
statement.close();
}
catch(SQLException e) { }
}
}

从上面可以看出事务的提交与回滚实际上所以依赖于transaction,再来看JdbcTransaction
//JdbcTransaction
public class JdbcTransaction
implements Transaction
{
protected Connection connection;//数据库连接
protected DataSource dataSource;//数据源
protected TransactionIsolationLevel level;//事务级别
protected boolean autoCommmit;
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit)
{
dataSource = ds;
level = desiredLevel;
autoCommmit = desiredAutoCommit;
}
//获取Connection
public Connection getConnection()
throws SQLException
{
if(connection == null)
openConnection();
return connection;
}
//打开Connection
protected void openConnection()
throws SQLException
{
if(log.isDebugEnabled())
log.debug("Openning JDBC Connection");
connection = dataSource.getConnection();
if(level != null)
//设置连接事务级别
connection.setTransactionIsolation(level.getLevel());
setDesiredAutoCommit(autoCommmit);
}
//提交事务
public void commit()
throws SQLException
{
if(connection != null && !connection.getAutoCommit())
{
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Committing JDBC Connection [").append(connection).append("]").toString());
connection.commit();
}
}
//回滚事务
public void rollback()
throws SQLException
{
if(connection != null && !connection.getAutoCommit())
{
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Rolling back JDBC Connection [").append(connection).append("]").toString());
connection.rollback();
}
}
//关闭事务
public void close()
throws SQLException
{
if(connection != null)
{
resetAutoCommit();
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Closing JDBC Connection [").append(connection).append("]").toString());
connection.close();
}
}
}

从上面可看出JdbcTransaction,依赖于具体的数据库。
总结:
[color=blue]事务的提交与回滚实际上所以依赖于transaction,transaction依赖于具体的数据库;清除缓存就是清空执行器的本地缓存;关闭SqlSession实际上是,通过执行器关闭statement。[/color]
这四条日志是 MyBatis 与 Spring 集成时,在事务管理过程中由 `SqlSessionUtils` 输出的调试信息,表示一个 SQL 会话(SqlSession)在事务提交并释放资源的过程。我们逐条解释其含义: --- ### 1. `Releasing transactional SqlSession [...]` ```text 2025-10-10 15:33:26,004 DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@51d0df1b] ``` **意思:** 当前线程正在释放一个与事务绑定的 SqlSession。 **解释:** Spring 使用 `ThreadLocal` 来管理当前线程中的 SqlSession。当你在使用 MyBatis 的 `SqlSessionTemplate` 或通过 `@Mapper` 注入的 Mapper 接口执行数据库操作时,Spring 会从当前事务上下文中获取或创建一个共享的 SqlSession。当方法执行完毕后,这个 SqlSession 不会被立即关闭,而是“释放”——即交还给 Spring 管理,等待事务结束时统一处理。 > 注意:“释放”不等于“关闭”,它只是表示当前操作不再使用该会话。 --- ### 2. `Transaction synchronization committing SqlSession [...]` ```text 2025-10-10 15:33:26,004 DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@51d0df1b] ``` **意思:** 事务同步器正在提交这个 SqlSession 对应的数据库事务。 **解释:** Spring 在事务提交阶段会触发一系列“事务同步回调”(Transaction Synchronization),MyBatis 注册了一个同步器来确保 SqlSession提交与 Spring 事务保持一致。 如果事务成功完成(没有抛出异常),则在此处调用 `sqlSession.commit()` 提交更改到数据库。 > 如果是只读事务或者没有进行任何修改,则可能不会真正提交,但日志仍会输出。 --- ### 3. `Transaction synchronization deregistering SqlSession [...]` ```text 2025-10-10 15:33:26,004 DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@51d0df1b] ``` **意思:** 将该 SqlSession 从当前事务的同步注册列表中移除。 **解释:** Spring 维护了一个事务同步管理器(`TransactionSynchronizationManager`),其中记录了哪些资源(如 SqlSession、DataSourceConnection 等)参与了当前事务。 当事务即将结束时,这些资源需要被“注销”(deregister),以防止后续误用或内存泄漏。 --- ### 4. `Transaction synchronization closing SqlSession [...]` ```text 2025-10-10 15:33:26,004 DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@51d0df1b] ``` **意思:** 正在关闭SqlSession。 **解释:** 这是整个流程的最后一步。只有当事务完全提交(或回滚)并且所有同步逻辑完成后,Spring 才会真正调用 `sqlSession.close()` 关闭会话,并清理 `ThreadLocal` 中的引用。 > 注意:如果是嵌套事务或多个 DAO 共享同一个事务上下文,SqlSession 可能不会在此刻关闭,而是在外层事务结束后才关闭--- ### 总结流程: | 日志 | 含义 | |------|------| | Releasing... | 释放会话控制权给 Spring | | Committing... | 提交事务(实际调用 sqlSession.commit()) | | Deregistering... | 从事务同步管理器中移除 | | Closing... | 最终关闭 SqlSession | 这四行日志通常出现在一个 **声明式事务(@Transactional)方法正常执行完毕并提交时**,属于正常行为,无需担心。 --- ### 相关问题示例代码(Java): 以下是一个典型的使用场景: ```java @Service @Transactional public class UserService { @Autowired private UserMapper userMapper; public void addUser(User user) { userMapper.insert(user); // 触发 SqlSession 创建和使用 } // 方法结束,自动提交事务 → 输出上述日志 } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值