作者:马跃
1 背景
这是一个宁静祥和没有 bug 的下午。
作为一只菜鸡,时刻坚固一下根底还是很有必要的,如此的大好时机,就让我来学习学习 mybatis 如何应用。
这可和我看到的不一样啊,让我来看看我的项目里怎么写的。
咱们我的项目中的 Dao 都继承于 BaseDao,而 BaseDao 继承于 SqlSessionDaoSupport,每次执行 sql 的时候都是间接将这个 sqlSession 返回,而后执行 sql,这难道不是一个实例变量嘛?这和你说的可不一样诶。于是带着这样的疑难,我开始了摸索。
2 探索之旅
1)咱们都晓得,在应用 mybatis 时,sqlSession 都来自于 sqlSessionFactory,而 sqlSessionFactory 能够通过 sqlSessionFactoryBuilder 创立,也能够通过 spring 初始化,而我的项目中很显然采取了后一种形式。
2)那么咱们曾经失去了 sqlSessionFactory,应该如何去进一步摸索 sqlSession 的起源呢,我想到能够通过我的项目中曾经实现的 dao 进行摸索。咱们轻易选取一个 dao 为例。
它继承了 BaseDao。
而 BaseDao 又继承了 SqlSessionDaoSupport,在 BaseDao 中调用了 getSqlSession 办法,实际上也就是 SqlSessionDaoSupport 的 getSqlSession 办法。
而 SqlSessionDaoSupport 的 getSqlSession 办法是间接将本人的成员变量返回去的,截至目前为止,和我的狐疑点是相符合的,即目前的写法和 mybatis 官网的阐明是抵触的。
3)重复浏览 SqlSessionDaoSupport 这个类后,终于被我发现了线索,仔细的小伙伴应该也早已发现了,就在上图之中的正文中,“用户应该应用这个办法来取得一个 SqlSession 来执行 sql 语句,这个 SqlSession 被 spring 治理,用户不应该提交、回滚或敞开它。因为这些曾经被主动执行了。”
同时,这个办法会返回一个线程平安的 SqlSession。
那么这个 SqlSession 是从何而来的呢,从上图能够看出,它有两种赋值形式,一种是给他传一个 SqlSessionFactory,生成 SqlSessionTemplate,SqlSessionTemplate 即为 sqlSession。另一种是间接给他传一个 SqlSessionTemplate 作为 SqlSession。依据本类的正文,如果 SqlSessionFactory 和 SqlSessionTemplate 都被定义了,那么 SqlSessionFactory 的形式会生效。至此,我的上述疑难曾经解决了,也就是说这个 SqlSession 并不是一个 mybatis 初始的 SqlSession,而是 spring 实现的 SqlSessionTemplate。
4)然而,我又诞生了新的疑难,SqlSessionTemplate 是怎么实现线程平安的呢?
于是我进入了 SqlSessionTemplate 的办法执行,发现理论执行语句的都是这个代理类 sqlSessionProxy。
而代理工作内容就在 SqlSessionInterceptor 这个 handler 里。
进入其中,咱们终于发现了它的获取和敞开操作。
也就是说,每次执行,代理都会调用 sessionFactory 的 openSession 办法取得一个新的 session。
3 总结
终于的终于,mybatis,spring,我的项目以及我的疑难失去了对立,真是一个平静祥和而又没有 bug 的下午呀。