SqlsessionTemplate线程安全解密

编程

SqlsessionTemplate线程安全解密

springboot中使用的是SqlsessionTemplate,而不是DefaultSqlsession,这个类是单例的,如何保证线程安全呢?

类图

源码解析

org.mybatis.spring.SqlSessionTemplate#selectList(java.lang.String),委托给代理

@Override

public <E> List<E> selectList(String statement) {

return this.sqlSessionProxy.<E> selectList(statement);

}

org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke,代理类核心方法

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 {

// 执行代理方法

Object result = method.invoke(sqlSession, args);

if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {

// force commit even on non-dirty sessions because some databases require

// a commit/rollback before calling close()

// 处理事务相关

sqlSession.commit(true);

}

return result;

} catch (Throwable t) {

Throwable unwrapped = unwrapThrowable(t);

if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {

// release the connection to avoid a deadlock if the translator is no loaded. See issue #22

closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);

sqlSession = null;

Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);

if (translated != null) {

unwrapped = translated;

}

}

throw unwrapped;

} finally {

if (sqlSession != null) {

closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);

}

}

}

org.mybatis.spring.SqlSessionUtils#getSqlSession(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)产生sqlSession方法

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {

notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);

notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);

SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

SqlSession session = sessionHolder(executorType, holder);

if (session != null) {

return session;

}

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Creating a new SqlSession");

}

// 产生DefaultSqlsession

session = sessionFactory.openSession(executorType);

registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);

return session;

}

总结

线程安全是通过代理来实现,代理里面每次产生了新的DefaultSqlsession来保证线程安全。

参考

  • https://www.cnblogs.com/daxin/p/3544188.html

以上是 SqlsessionTemplate线程安全解密 的全部内容, 来源链接: utcz.com/z/514766.html

回到顶部