基本概念
- SqlSession:
- 数据库CRUD及事务操作接口
- 线程不安全,常用于Request范围或method范围
// Request范围,4次sql执行共用一个SqlSession
sqlSessionManager.startManagedSession();
try {
sqlSessionManager.query1();
sqlSessionManager.query2();
sqlSessionManager.update1();
sqlSessionManager.update2();
//...
}catch (Throwable t) {
sqlSessionManager.rollback();
} finally {
sqlSessionManager.close();
}
// 方法范围,两次调用创建了两个session
SqlSessionManager.query1();
SqlSessionManager.query2();
- SqlSessionFactory
- SqlSessionManager/SqlSessionTemplate[装饰器模式]
- SqlSession装饰器
- 增强SqlSession生命周期管理

SqlSessionManager/SqlSessionTemplate源码分析
public class SqlSessionManager implements SqlSessionFactory, SqlSession {
private final SqlSessionFactory sqlSessionFactory;
private final SqlSession sqlSessionProxy;
private final ThreadLocal localSqlSession = new ThreadLocal();
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSession.class},
new SqlSessionInterceptor());
}
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) {
try {
return method.invoke(sqlSession, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} else {
final SqlSession autoSqlSession = openSession();
try {
final Object result = method.invoke(autoSqlSession, args);
autoSqlSession.commit();
return result;
} catch (Throwable t) {
autoSqlSession.rollback();
throw ExceptionUtil.unwrapThrowable(t);
} finally {
autoSqlSession.close();
}
}
}
}
}
/**
* 1. Thread safe, Spring managed, {@code SqlSession} that works with Spring
* transaction management to ensure that that the actual SqlSession used is the
* one associated with the current Spring transaction.
* spring管理,线程安全,确保SqlSession是当前spring事务的sqlSession
* 2. SqlSession生命周期管理,包括commit, rollback, close
* 3. 单例,所有DAO可以共用一个
*/
public class SqlSessionTemplate implements SqlSession, DisposableBean {
private final SqlSessionFactory sqlSessionFactory;
private final ExecutorType executorType;
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());
}
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
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)) {
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
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);
}
}
}
}
}
/**
* 1. 非事务SqlSession,close
* 2. 事务sqlsession, 更新引用计数器,当计数器为0,即事务结束时,spring调用close callback
*/
public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) {
......
}
- Spring SqlSessionTemplate SqlSession生命周期管理
- SqlSessionTemplate与SqlSessionManager实现SqlSession生命周期管理的方式相同
- SqlSessionManager由使用者决定是否共用SqlSession
- SqlSessionTemplate由Spring事务管理器决定是否共用SqlSession。
- 事务内部共用SqlSession
- 非事务不共用SqlSession
Spring创建SqlSessionFactory, SqlSessionTemplate, SqlSession流程
spring配置
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="*.dao" />
bean>

MapperProxy
- DAO动态代理类:拦截DAO方法调用,调用SqlSession执行SQL,返回结果
- Spring中采用SqlSessionTemplate执行SQL,对SqlSession的生命周期管理进行增强
public class MapperProxy<T> implements InvocationHandler, Serializable {
private final SqlSession sqlSession;
private final Class mapperInterface;
private final Map methodCache;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
......
}
Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, new MapperProxy(sqlSession, mapperInterface, methodCache))
JAVA动态代理