MyBatis创建SqlSession可以直接使用DefaultSqlSession 吗?

论坛 期权论坛 脚本     
匿名技术用户   2021-1-5 09:22   42   0

我们现在已经有一个DefaultSqlSessionFactory,按照编程式的开发过程,我们接下来就会创建一个SqlSession 的实现类,但是在Spring 里面,我们不是直接使用DefaultSqlSession 的,而是对它进行了一个封装,这个SqlSession 的实现类就是SqlSessionTemplate。这个跟Spring 封装其他的组件是一样的,比如JdbcTemplate,RedisTemplate 等等,也是Spring 跟MyBatis 整合的最关键的一个类。

为什么不用DefaultSqlSession?它是线程不安全的,注意看类上的注解:

Note that this class is not Thread-Safe.

而SqlSessionTemplate 是线程安全的。

* Thread safe, Spring managed, {@code SqlSession} that works with Spring

回顾一下SqlSession 的生命周期:

对象生命周期
SqlSessionFactoryBuiler方法局部(method)
SqlSessionFactory(单例)应用级别(application)
SqlSession请求和操作(request/method)
Mapper方法(method)

在编程式的开发中,SqlSession 我们会在每次请求的时候创建一个,但是Spring里面只有一个SqlSessionTemplate(默认是单例的),多个线程同时调用的时候怎么保证线程安全?

思考:为什么SqlSessionTemplate 是线程安全的?

思考:在编程式的开发中,有什么方法保证SqlSession 的线程安全?

SqlSessionTemplate 里面有DefaultSqlSession 的所有的方法:selectOne()、selectList()、insert()、update()、delete(),不过它都是通过一个代理对象实现的。这个代理对象在构造方法里面通过一个代理类创建:

this.sqlSessionProxy = (SqlSession) newProxyInstance(
 SqlSessionFactory.class.getClassLoader(),
 new Class[] { SqlSession.class },
 new SqlSessionInterceptor());

所有的方法都会先走到内部代理类SqlSessionInterceptor 的invoke()方法:

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); 

首先会使用工厂类、执行器类型、异常解析器创建一个sqlSession,然后再调用sqlSession 的实现类,实际上就是在这里调用了DefaultSqlSession 的方法。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP