mybatis如何和spring的事务结合的
PlatformTransactionManager (平台)事务管理器
public interface PlatformTransactionManager {
// 根据指定的传播行为,返回当前活动的事务或创建一个新事务。
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// 使用事务目前的状态提交事务
void commit(TransactionStatus status) throws TransactionException;
// 对执行的事务进行回滚
void rollback(TransactionStatus status) throws TransactionException;
}
TransactionDefinition 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则
TransactionStatus 事务运行状态
spring对方法加有@Transactional的方法进行拦截
org.springframework.transaction.interceptor.TransactionInterceptor#invoke
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
protected void doBegin(Object transaction, TransactionDefinition definition) {
//将 Connection 放入到 TransactionSynchronizationManager
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
mybatis中拿到和spring管理的Connection
// org.apache.ibatis.executor.SimpleExecutor#prepareStatement
protected Connection getConnection(Log statementLog) throws SQLException {
//从 SpringManagedTransaction拿到 connection
Connection connection = transaction.getConnection();
}
// org.mybatis.spring.transaction.SpringManagedTransaction#openConnection
private void openConnection() throws SQLException {
//从Spring管理的连接中拿到 connection
this.connection = DataSourceUtils.getConnection(this.dataSource);
}
//org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
//从TransactionSynchronizationManager拿到数据库连接
ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);
}
但是我们知道我们使用mybatis-spring的时候使用了SqlSessionTemplate这里也会进行事务操作比如
对Mapper代理对象调用进行拦截
// org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//...获取SqlSession
SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
try {
//调用SqlSession来执行sql
Object result = method.invoke(sqlSession, args);
//判断当前sqlSession是否在当前事物当中
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
//...省略方法
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
// org.mybatis.spring.SqlSessionUtils#isSqlSessionTransactional
public static boolean isSqlSessionTransactional(SqlSession session, SqlSessionFactory sessionFactory) {
SqlSessionHolder holder = (SqlSessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
return (holder != null) && (holder.getSqlSession() == session);
}
// org.mybatis.spring.SqlSessionUtils#closeSqlSession
public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) {
SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if ((holder != null) && (holder.getSqlSession() == session)) {
holder.released();
} else {
session.close();
}
}
网友评论