文章目录
三个SqlSession
DefaultSqlSession与SqlSessionManager 与SqlSessionTemplate 是我常见的3种sqlsesion
从类图可以看出他们三个都实现了了SqlSession,也就是他们都可以表示一个会话。与其他不同的是SqlSessionManager实现了SqlSessionFactory
这三种sqlsession的区别是啥?他们的应用场景是啥呢?
这一切我们从DefaultSqlSession开始说起。
DefaultSqlSession
DefaultSqlSession 是SqlSession的默认实现。
当我们单独使用Mybatis时,我们通常使用DefaultSqlSession 来执行SQL,操作数据库。
String resource = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
// 构建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
User user = sqlSession.selectOne("MyMapper.selectUser", 1);
System.out.println(user);
} finally {
sqlSession.close();
}
但是DefaultSqlSession存在两个不足。
- 我们需要自己手动关闭sqlsesion,我们知道,人总是不可靠的。忘关sqlsession 是有很大概率发生的
- 线程安全问题:DefaultSqlSession是线程不安全的Sqlsession 。也就是说DefaultSqlSession不能是单例,
如何解决这两个问题?
自动关闭Session问题:
- 我可以自己做一个切面,专门处理session关闭问题
- Mybatis为我们提供了升级版的DefaultSqlSession, SqlSessionManager可以解决这个问题
线程安全问题:
- 既然不能共用,很自然的,我们每次使用DefaultSqlSession的时候都从SqlSessionFactory当中获取一个就可以了啊。
- 但是我们仍然想使用单例版的Sqlsession怎么办?别慌,Mybatis为我们提供了升级版的DefaultSqlSession ,SqlSessionManager可以解决这个问题。
SqlSessionManager
个人认为,与其说SqlSessionManager是DefaultSqlSession 的升级版,不如说SqlSessionManager是DefaultSqlSession代理版(或者封装版)
为什么这样说?来看看SqlSessionManager能干吗
1.获取DefaultSqlSession的能力
String resource = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionManager sqlSessionManager =SqlSessionManager.newInstance(inputStream);
//获取一个SqlSession
SqlSession session = sqlSessionManager.openSession();
//SqlSessionManager 类的openSession
public SqlSession openSession() {
return sqlSessionFactory.openSession();
}
从这个角度看,其实他跟SqlSession没有什么区别。他只是封装了SqlSession ,具体工作还是交给SqlSession去做的.
sqlSessionManager.openSession() = sqlSessionFactory.openSession()
得到的Sqlsession自然也是DefaultSqlSession
2.解决DefaultSqlSession的不足
2.1解决自动关闭问题
为了解决自动关闭问题,SqlSessionManager使用了代理技术来实现了自动关闭问题。
使用JDK动态代理技术,动态生成代理对象sqlSessionProxy ,并用内部类SqlSessionInterceptor来对SqlSession的执行方法进行增强。
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
//使用JDK代理技术,生成一个代理对象
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]