本文主要是介绍1. Mybatis 中 SqlSession接口的三种实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Mybatis 中 SqlSession接口的三种实现
SqlSession
是一个接口,并且里面包含了许多 CRUD 操作数据库等方法。
SqlSession
它有三个实现类,分别是 SqlSessionManager
、DefaultSqlSession
和 SqlSessionTemplate
,其中 DefaultSqlSession
它的默认实现类。
DefaultSqlSession 是线程不安全的 Sqlsession 。也就是说 DefaultSqlSession 不能是单例,必须是多例的。
SqlSessionManager
和 SqlSessionTemplate
是 SqlSession 的代理版,每次新建一个代理对象。姿势都是一样的,但是代理逻辑SqlSessionInterceptor 是不一样的。
代理 DefaultSqlSession 实现复用
在执行 getSqlSession 时,两则都是利用 SessionFactory 工厂创建一个 DefaultSqlSession。然后尽可能复用 DefaultSqlSession,而非多例的每次使用都创建一个 DefaultSqlSession。
SqlSession session = sessionFactory.openSession(executorType);
不同之处在于复用逻辑,先看 SqlSessionTemplate 的:
SqlSessionTemplate
会将 SqlSession 封装成 SqlSessionHolder,并有利用引用计数法,当 referenceCount>0。表示 SqlSession 还在使用。- 将 sqlSessionHolder 存放到
TransactionSynchronizationManager
的synchronizations
中。synchronizations
是一个 set 集合。
相对 SqlSessionTemplate 的,SqlSessionManage 的比较简单一点。
- SqlSessionManage 内部有一个线程私有变量 localSqlSession。
private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal();
- SqlSessionManage 会将 DefaultSqlSession 放入到 ThreadLocal 线程私有的变量 localSqlSession 中
- 用的时候先从 localSqlSession 中获取 DefaultSqlSession,如果没有获取到则创建。
SqlSessionManager 的代理逻辑
private SqlSessionManager(){this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(),new Class[]{SqlSession.class}, new SqlSessionInterceptor());
}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {SqlSession sqlSession = (SqlSession)SqlSessionManager.this.localSqlSession.get();if (sqlSession != null) {return method.invoke(sqlSession, args);} else {SqlSession autoSqlSession = SqlSessionManager.this.openSession();Object var8;try {try {Object result = method.invoke(autoSqlSession, args);autoSqlSession.commit();var8 = result;} catch (Throwable var20) {autoSqlSession.rollback();throw ExceptionUtil.unwrapThrowable(var20);}} catch (Throwable var21) {} finally {if (autoSqlSession != null) {autoSqlSession.close(); }}return var8;}
}
SqlSessionTemplate 的代理逻辑
private SqlSessionTemplate(){this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionInterceptor());
}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);Object unwrapped;try {Object result = method.invoke(sqlSession, args);if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {sqlSession.commit(true);}unwrapped = result;} catch (Throwable var11) {unwrapped = ExceptionUtil.unwrapThrowable(var11);if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);sqlSession = null;Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);if (translated != null) {unwrapped = translated;}}throw (Throwable)unwrapped;} finally {if (sqlSession != null) {SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);}}return unwrapped;
}
这篇关于1. Mybatis 中 SqlSession接口的三种实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!