Mybatis【2.2】-- Mybatis关于创建SqlSession源码分析的几点疑问?
代码直接放在Github仓库【https://github.com/Damaer/Mybatis-Learning 】,可直接运行,就不占篇幅了。
1.为什么我们使用SQLSessionFactoryBuilder的时候不需要自己关闭流?
我们看我们的代码:
当我们使用inputStream = Resources.getResourceAsStream("mybatis.xml");
的时候,我们并需要去关闭inputstream,我们可以查看源码,首先看到SqlSessionFactoryBuilder().build()
这个方法:
跟进去,我们再来看另一个build方法,里面有一个finally模块,无论怎么样都会执行close方法,所以这就是为什么我们在使用的时候为什么不用关闭inputstream的原因:因为这个流是在finally代码块中被关闭了。
2. Sqlsession是如何创建的?
语句里面执行代码:使用SQLSessionFactory
去打开一个session
,这里的session
我们可以初步理解为一个sql
的会话,类似我们想要发信息给别人,肯定需要打开一个和别人的会话。
我们需要查看源码,我们发现opensession是sqlSessionFactory的一个接口方法,sqlSessionFactory是一个接口。
idea选中该方法,ctrl + alt +B
,我们可以发现有DefaultSqlSessionFactory,和SqlSessionManager这两个类实现了SqlSessionFactory这个接口
那么我们需要跟进去DefaultSqlSessionFactory这个类的openSesseion方法,在里面调用了一个封装好的方法:openSessionFromDataSource()
当然在DefaultSqlSessionFactory
这个类里面还有一个方法,参数是autoCommit,也就是可以指定是否自动提交:
我们再跟进去源码,我们会发现有一个参数是autoCommit
,也就是自动提交,我们可以看到上一步传值是false,也就是不会自动提交,通过configuration(主配置)获取environment(运行环境),然后通过environment(环境)开启和获取一个事务工厂,通过事务工厂获取事务对象Transaction,通过事务对象创建一个执行器executor,Executor是一个接口,实现类有比如SimpleExecutor,BatchExecutor,ReuseExecutor,所以我们下面代码里的execType,是指定它的类型,生成指定类型的Executor,把引用给接口对象,有了执行器之后就可以return一个DefaultSqlSession对象了。
我们跟 var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
这句代码,我们这是初始化函数赋值于各个成员变量,我们发现里面有一个dirty成员,这是干什么用的呢?从名字上来讲我们理解是脏的,这里既然设置为false,那就是不脏的意思。那到底什么是脏呢?脏是指内存里面的数据与数据库里面的数据存在不一致的问题,如果一致就是不脏的
后面会解释这个dirty的作用之处,到这里一个SqlSession就创建完成了。
3.增删改是怎么执行的
我们使用到这句代码:
我们发现同样是接口方法,上面我们知道SqlSession其实是DefaultSqlSession所实现的接口,那么我们跟进去DefaultSqlSession的insert()方法,我们发现其实inset方法底层也是实现了update这个方法,同样的delete方法在底层也是调用了update这个方法,增,删,改本质上都是改。
那么我们现在跟进去update方法中,dirty变成ture,表明即将改数据,所以数据库数据与内存中数据不一致了,statement是我们穿过来的id,这样就可以通过id拿到statement的对象,然后就通过执行器执行修改的操作:
4.SqlSession.commit()为什么可以提交事务(transaction)?
首先,我们使用到的源码,同样选择DefaultSqlSession这个接口的方法,我们发现commit里面调用了另一个commit方法,传进去一个false的值:
我们跟进去,发现上面传进去的false是变量force,里面调用了一个isCommitOrRollbackRequired(force)
方法,执行的结果返回给commit方法当参数。
我们跟进去isCommitOrRollbackRequired(force)
这个方法,这个方法从命名上是需要提交还是回滚的意思。在前面我们知道autoCommit是false,那么取反之后就是true,关于dirty我们知道前面我们执行过insert()方法,insert的底层调用了update方法,将dirty置为true,表示即将修改数据,那我们知道!this.autoCommit && this.dirty
的值就是true,那么就短路了,所以整个表达式的值就是true。
返回上一层的,我们知道this.isCommitOrRollbackRequired(force)
的返回值是true。
跟进去commit方法,这个commit方法是一个接口方法,实现接口的有BaseExecutor,还有CachingExecutor,我们选择BaseExecutor这个接口实现类:
5.为什么sqlsession关闭就不需要回滚了?
假如我们在上面已经提交过了,那么dirty的值就为false。我们使用的是sqlSession.close();
,跟进去源码,同样是接口,我们跟DefaoultSqlsession的方法,同样调用了isCommitOrRollbackRequired()这个方法:
我们跟进去isCommitOrRollbackRequired(false)这个方法,我们知道force传进来的值是false,autoCommit是false(只要我们使用无参的sqlSessionFactory.openSession();
),取反之后!autoCommit是true,但是dirty已经是false,所以!this.autoCommit && this.dirty
的值是false,那么force也是false,所以整一个表达式就是false:
我们返回上一层,executor.close()方法,参数是false:
跟进去close()方法,forceRollback的值是false,我们发现有一个this.rollback(forceRollback)
:
我们跟进去rollback()这个方法,我们可以发现required是fasle,所以 this.transaction.rollback();
是不会执行的,这个因为我们在前面做了提交了,所以是不用回滚的:
假如我们现在执行完insert()方法,但是没有使用commit(),那么现在的dirty就是true,也就是数据库数据与内存的数据不一致。我们再执行close()方法的时候,dirty是true,!this.autoCommit是true,那么整个表达式就是true。
返回上一层,close的参数就会变成true
close()方法里面调用了 this.rollback(forceRollback);
,参数为true,我们跟进去,可以看到确实执行了回滚:
所以只要我们执行了提交(commit),那么关闭的时候就不会执行回滚,只要没有提交事务,就会发生回滚,所以里面的dirty是很重要的。
【作者简介】:
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。这个世界希望一切都很快,更快,但是我希望自己能走好每一步,写好每一篇文章,期待和你们一起交流。
此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者核实删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~
__EOF__

本文链接:https://www.cnblogs.com/Damaer/p/14052603.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库