Mybatis - 三种SqlSession实现的区别
记录学习过程笔记
如果本文有任何错误,请批评指教,不胜感激 !
1、DefaultSqlSession
package org.apache.ibatis.session.defaults;
/**
* 默认实现
* 不是线程安全
*/
public class DefaultSqlSession implements SqlSession {
}
1. 使用示例
- 需要手动关闭
- 不是线程安全
public static void main(String[] args) {
String resource = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
// 构建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
User user = sqlSession.selectOne("com.hhc.UserMapper.selectUser");
System.out.println(user);
} finally {
sqlSession.close();
}
}
2、SqlSessionManager
- 动态代理,由代理对象解决 sqlSession关闭问题
- ThreadLocal保存sqlSession,解决线程安全问题
public class SqlSessionManager implements SqlSessionFactory, SqlSession {
// 生成代理对象,解决 session关闭问题
private final SqlSession sqlSessionProxy;
// ThreadLocal解决线程安全问题
private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>();
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSession.class},
new SqlSessionInterceptor());
}
// 开启本地线程变量管理
public void startManagedSession() {
this.localSqlSession.set(openSession());
}
// 代理处理
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();
if (sqlSession != null) {
}else {
final SqlSession autoSqlSession = openSession();
try{}catch (Throwable t) {}
finally {
autoSqlSession.close();
}
}
}
}
1. 使用示例
public static void main(String[] args) {
String resource = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionManager sqlSessionManager =SqlSessionManager.newInstance(inputStream);
// 可选:绑定Session到线程本地变量
sqlSessionManager.startManagedSession();
User user = sqlSessionManager.selectOne("com.hhc.UserMapper.selectUser");
System.out.println(user);
}
3、SqlSessionTemplate
- 是Mybatis与Spring 整合时使用的线程安全sqlsession
- 动态代理,由代理对象解决 sqlSession关闭问题
- TransactionSynchronizationManager使用ThreadLocal保存sqlSession,解决线程安全问题
public class SqlSessionTemplate implements SqlSession, DisposableBean {
// 生成代理对象,解决 session关闭问题
private final SqlSession sqlSessionProxy;
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator) {
notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
notNull(executorType, "Property 'executorType' is required");
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
try{
// 执行sql
}catch (Throwable t) {
// 关闭SqlSession
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// SqlSessionUtils.getSqlSession
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
}
}
}
SqlSessionUtils
- 尝试从TransactionSynchronizationManager事务同步器获取sqlsesion
- 如果获取不到,则从sqlSessionFactory工厂获取,再注册绑定到TransactionSynchronizationManager事务同步器
- session 如果是由TransactionSynchronizationManager管理的,则只会更新引用计数器,让Spring在托管事务结束时调用close回调,关闭session。
- session不是由TransactionSynchronizationManager 管理的,则直接关闭session
package org.mybatis.spring;
public final class SqlSessionUtils {
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
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");
}
session = sessionFactory.openSession(executorType);
registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
return session;
}
// 关闭session
public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) {
notNull(session, NO_SQL_SESSION_SPECIFIED);
notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);
// 是否由TransactionSynchronizationManager管理
SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if ((holder != null) && (holder.getSqlSession() == session)) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Releasing transactional SqlSession [" + session + "]");
}
// 计数-1
holder.released();
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Closing non transactional SqlSession [" + session + "]");
}
// 关闭session
session.close();
}
}
}
记录学习过程笔记
如果本文有任何错误,请批评指教,不胜感激 !