先看一段代碼:
@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