先看一段代码:

    1. @Service
    2. public class TblEmployeeServiceimpl implements TblEmployeeService {
    3. @Autowired
    4. private TblEmployeeMapper tblEmployeeMapper;
    5. @Override
    6. public TblEmployeePO select(Integer id) {
    7. TblEmployeePO tblEmployeePO=new TblEmployeePO();
    8. tblEmployeePO = tblEmployeeMapper.selectByPrimaryKey(id);
    9. return tblEmployeePO;
    10. }
    11. }
    12. //jmeter测试: https://jingyan.baidu.com/article/eb9f7b6d52079d869364e825.html

    每请求一次数据库就创建一个SqlSession,这是为啥呢?

    Spring+Mybatis 每次请求数据库,为什么都会创建一个SqlSesssion? - 图1
    容器启动时:
    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