1

一个宁静祥和没有bug的下午和SqlSession的故事 - 京东云开发者

 1 year ago
source link: https://www.cnblogs.com/Jcloud/p/16912021.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这是一个安静祥和没有bug的下午。
作为一只菜鸡,时刻巩固一下基础还是很有必要的,如此的大好时机,就让我来学习学习mybatis如何使用。

8870f2b1-f523-4f77-9729-f6c4620bfc0020220407135153.png

这可和我看到的不一样啊,让我来看看项目里怎么写的。

1999d5da-a31a-4e06-baf9-7d20f9a5ab5820220407135204.png

我们项目中的Dao都继承于BaseDao,而BaseDao继承于SqlSessionDaoSupport,每次执行sql的时候都是直接将这个sqlSession返回,然后执行sql,这难道不是一个实例变量嘛?这和你说的可不一样诶。于是带着这样的疑问,我开始了探索。

2 探索之旅

1)我们都知道,在使用mybatis时,sqlSession都来自于sqlSessionFactory,而sqlSessionFactory可以通过sqlSessionFactoryBuilder创建,也可以通过spring初始化,而项目中很显然采取了后一种方式。

4c3b639a-9212-44b4-9bce-e7565920f73a20220407135314.png

2)那么我们已经得到了sqlSessionFactory,应该如何去进一步探索sqlSession的来源呢,我想到可以通过项目中已经实现的dao进行探索。我们随便选取一个dao为例。

0fed4ff0-adfa-4347-9f20-380a6f83966c20220407135330.png

它继承了BaseDao。

82cc7511-1613-42d7-aeef-e0ecb82ca93920220407135344.png

而BaseDao又继承了SqlSessionDaoSupport,在BaseDao中调用了getSqlSession方法,实际上也就是SqlSessionDaoSupport的getSqlSession方法。

2b61bb78-e795-461c-8717-aab73817b0f520220407135357.png

而SqlSessionDaoSupport的getSqlSession方法是直接将自己的成员变量返回去的,截至目前为止,和我的怀疑点是相符合的,即目前的写法和mybatis官网的说明是冲突的。

3)反复阅读SqlSessionDaoSupport这个类后,终于被我发现了线索,细心的小伙伴应该也早已发现了,就在上图之中的注释中,“用户应该使用这个方法来获得一个SqlSession来执行sql语句,这个SqlSession被spring管理,用户不应该提交、回滚或关闭它。因为这些已经被自动执行了。”

同时,这个方法会返回一个线程安全的SqlSession。

6b698b48-a469-447a-8a8f-b3f5f772234620220407135426.png

那么这个SqlSession是从何而来的呢,从上图可以看出,它有两种赋值方式,一种是给他传一个SqlSessionFactory,生成SqlSessionTemplate,SqlSessionTemplate即为sqlSession。另一种是直接给他传一个SqlSessionTemplate作为SqlSession。根据本类的注释,如果SqlSessionFactory和SqlSessionTemplate都被定义了,那么SqlSessionFactory的方式会失效。至此,我的上述疑问已经解决了,也就是说这个SqlSession并不是一个mybatis初始的SqlSession,而是spring实现的SqlSessionTemplate。

4)但是,我又诞生了新的疑问,SqlSessionTemplate是怎么完成线程安全的呢?

59aef18c-da90-4ce6-a879-c495265d755920220407135446.png

于是我进入了SqlSessionTemplate的方法执行,发现实际执行语句的都是这个代理类sqlSessionProxy。

297b5522-2f52-4f39-a2ea-5911246dedb520220407135502.png

而代理工作内容就在SqlSessionInterceptor这个handler里。

43323d1a-94c7-40a2-a4e7-8471e46421d520220407135515.png

进入其中,我们终于发现了它的获取和关闭操作。

9ad99785-bb7a-43e3-8525-e17446a03d6120220407135529.png
db6aee0a-3d28-4c76-9185-51c32427e07d20220407135543.png

也就是说,每次执行,代理都会调用sessionFactory的openSession方法获得一个新的session。

终于的终于,mybatis,spring,项目以及我的疑问得到了统一,真是一个宁静祥和而又没有bug的下午呀。


作者:马跃


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK