mybatis与spring集成中一级缓存失效的原因
一、缓存失效的原因
首先要明确一个知识点,就是关于一级缓存生效的条件,其中一个条件就是一级缓存只在同一会话中生效,也就是同一个session。明确这一点,也就知道spring中如果不配置事务就会导致一级缓存失效的原因。
spring中使用的sqlsession会话时SqlSessionTemplate,也实现了SqlSession接口。
// session工厂,里面携带了configuration等重要信息 private final SqlSessionFactory sqlSessionFactory; // 执行器的种类,具体执行数据库操作 private final ExecutorType executorType; // 是一个session代理类,也是sqlsessionTemplate中实际执行的类 private final SqlSession sqlSessionProxy; private final PersistenceExceptionTranslator exceptionTranslator;
SqlSessionTemplate中最重要的就是其内部类,SqlSessionInterceptor
private class SqlSessionInterceptor implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在代理执行session操作时,会首先去获得一个sqlsession // 这也就是为什么说spring在不配置事务的情况下会生成不同会话的原因 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); } } } }
进入getSqlSession看看更深入的源码,是否跟上面所说一样呢?
// SqlSessionUtils中产生session的工具方法 public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED); notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED); // 这里就看到了Transaction,先尝试通过事务去获取会话 SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); SqlSession session = sessionHolder(executorType, holder); // 如果获取了会话,就返回该session if (session != null) { return session; } LOGGER.debug(() -> "Creating a new SqlSession"); // 否则就新创建一个session // 所以说会产生不同的会话 session = sessionFactory.openSession(executorType); registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session); return session; }
浙公网安备 33010602011771号