先看一段代码:
@Service
public class TblEmployeeServiceimpl implements TblEmployeeService {
@Autowired
private TblEmployeeMapper tblEmployeeMapper;
@Override
public TblEmployeePO select(Integer id) {
TblEmployeePO tblEmployeePO=new TblEmployeePO();
tblEmployeePO = tblEmployeeMapper.selectByPrimaryKey(id);
return tblEmployeePO;
}
}
//jmeter测试: https://jingyan.baidu.com/article/eb9f7b6d52079d869364e825.html
每请求一次数据库就创建一个SqlSession,这是为啥呢?
容器启动时:
Spring调用MapperFactoryBean.getObject()来生成Dao代理MapperyProxy分成如下两步:getSqlSession()和getMapper(this.mapperInterface)
public T getObject() throws Exception {
return this.getSqlSession().getMapper(this.mapperInterface);
}
看看这个getSqlSession方法
SqlSessionDaoSupport类:
public SqlSession getSqlSession() {
return this.sqlSessionTemplate;
}
//发现sqlSessionTemplate的值由createSqlSessionTemplate获得
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
this.sqlSessionTemplate = this.createSqlSessionTemplate(sqlSessionFactory);
}
}
//直接new了一个SqlSessionTemplate
protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
SqlSessionTemplate类:一直跟进SqlSessionTemplate的构造方法
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
Assert.notNull(sqlSessionFactory, “Property ‘sqlSessionFactory’ is required”);
Assert.notNull(executorType, “Property ‘executorType’ is required”);
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor());
}
到最后,发现SqlSessionTemplate,有一个属性SqlSession,是一个SqlSession的代理对象,SqlSessionTemplate本身也是一个SqlSession。并且在new SqlSessionTemplate的时候,通过构造函数给sqlSessionProxy 创建了一个sqlsession代理对象。
public class SqlSessionTemplate implements SqlSession, DisposableBean {
private final SqlSessionFactory sqlSessionFactory;
private final ExecutorType executorType;
private final SqlSession sqlSessionProxy;
private final PersistenceExceptionTranslator exceptionTranslator;
现在来看看创建sqlsession代理对象用到的拦截器SqlSessionInterceptor的invoke方法
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;
}
过程:
进入请求,先生成一个新的sqlSession,为本次db操作做准备;
通过反射调用请求进来的方法,将 sqlSession 回调,进行复杂查询及结果映射;
如果需要立即提交事务,do it;
如果出现异常,包装异常信息,重新抛出;
操作完成后,关闭本次session;
看第一步:SqlSessionUtils.getSqlSession,生成一个新的sqlSession
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
Assert.notNull(sessionFactory, “No SqlSessionFactory specified”);
Assert.notNull(executorType, “No ExecutorType specified”);
SqlSessionHolder holder = (SqlSessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
SqlSession session = sessionHolder(executorType, holder);
if (session != null) {
return session;
} else {
LOGGER.debug(() -> {
return “Creating a new SqlSession”;
});
//创建一个sqlsession
session = sessionFactory.openSession(executorType);
registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
return session;
}
}
看到了熟悉的日志 “Creating a new SqlSession”,同时还创建了一个sqlsession。
回到SqlSessionTemplate :可以看到SqlSessionTemplate的增删改查实际上用的是sqlsession代理类。而使用代理类执行增删改查,实际上就是执行代理类的invoke方法,而sqlsession代理类的invoke方法的第一步就是新建一个SqlSession。这下总算明白啦。
https://www.cnblogs.com/yougewe/p/10072740.html
https://blog.csdn.net/mayongzhan_csdn/article/details/78481987
https://www.xttblog.com/?p=4018