MyBatis学习及SpringBoot对MyBatis的封装

以前只是简单的用了一下MyBatis,对于内部是如何工作的并不清楚

 

以下是从各个网站找到的MyBatis的原理

启动/初始化:
SqlSessionFactory(接口):创建的是DefaultSqlSessionFactory,会完成全局配置文件和映射文件的加载解析操作,把配置相关的信息保存在factory的Configuration中

处理请求:

通过SqlSessionFactory获取SqlSession对象,创建的是DefaultSqlSession

SqlSession提供了select、update、delete、save等方法,通过这些API(参数是sql的接口名)来操作数据库

调用对应的Executor进行处理,有配置缓存的话,先走二级缓存,没有命中再走一级缓存,再没有命中就操作数据库,交给StatementHandler来处理

通过ParameterHandler处理SQL的占位符

通过ResultSetHandler处理结果的映射

最后关闭session

 

 

实践一下,基于SpringBoot2.7 + mybatis-spring-boot-starter 2.3.2

上来就有问题了,我不需要配置mybatis-config.xml就能工作,想着应该是spring的约定优于配置,可能是有默认的配置吧

于是网上一搜,说是SpringBoot的话整合到了MybatisProperties里了,默认可以不配置

比如我要清空一级缓存的话就在properties里配置

 mybatis.configuration.local-cache-scope=STATEMENT

根据上述所说,我来看看我的这个配置有没有生效

 

接下来按上面说的就是处理请求的时候会创建session

写个controller,调用一下这个接口,怎么回事,debug发现我的请求进来,sqlSession都是同一个呢,根本没有所谓的openSession和closeSession,而且这个变量是个final,难道上面说法不对

不过这个SqlSession不是上面说的DefaultSqlSession,而是SqlSessionTemplate

 

对比这两家伙,都是实现了SqlSession,但是package不一样,一个是mybatis原生的,一个是spring的,都不是同一个mother 

看样子可能SqlSessionTemplate是mybatis为了SpringBoot又加的一些东西,而且这个SqlSession都不支持手动的commit,rollback

 

看看源码里是怎么注释的,大概就是说,SqlSessionTemplate是线程安全的,单例的,和Spring事务能够兼容,而且完全由Spring事务来管理session的生命周期。

 那如果没有Spring事务呢,我们后面再来解释

再从service层调用开始debug

首先,MyBatis (Spring)启动的时候,使用JDK动态代理,把单例的SqlSessionTemplate作为参数来实例化各个mapper,

然后调用mapper的方法时,就会进入到MapperProxy的invoke方法,然后执行MapperMethod的execute方法,根据sql的类型(增删改查)调用sqlsession不同的API

 

 

进入到SqlSessionTemplate,怎么还有动态代理,以前我大概知道会对mapper的接口进行动态代理,没想到SqlSession里面还有,盲猜可能是为了处理事务相关的东西,commit,rollback相关的东西,毕竟SqlSessionTemplate不支持手动调用rollback,commit等

 

 

此处是代理了DefaultSqlSession,原来是在这里去获取了真正的sqlSession,调用sqlSession

 此处通过动态代理去反射调用sqlSession的API,然后调用Executor去执行sql语句,包括执行前sql语句处理参数,执行完对结果集的处理和映射,因为此处的service方法上我加了@Transaction注解,所以上图197行的commit是不会去执行的,具体的commit是交由Spring 事务管理来控制。

 

 所以网上说的还是没错,只不过Spring帮我们做了session的创建,commit和rollback,并且根据Spring的事务来决定此次sql语句是否commit,这就回答了上面,

如果没有Spring事务 =》 那就直接commit

如果有Spring事务,sqlSession会尝试从SqlSessionHolder里面拿,拿不到(说明这是此次事务里的第一个sqlSession)就新open一个session,然后执行完sql语句后并不去commit,而是最后在Transaction提交事务的时候,调用sqlSession的commit。

 

 

总结:

网上说的不错,是mybatis的核心处理过程,而我们日常使用的是SpringBoot+MyBatis,Spring帮我们做了很多东西,包括open session、commit、rollback和close,并且是和Spring的事务绑定在一起。

 
另外,说一下两次动态代理的作用
针对mapper接口的代理: 实现了数据库的请求操作,包括处理输入参数,执行sql语句,映射结果集,处理二级、一级缓存的逻辑
针对sqlSession的代理: 与Spring的事务管理融合在一起,封装了sqlSession的一系列操作,sqlSession的open,调用Executor,进行commit/rollback,close
 
posted @ 2024-03-18 16:57  坏男银  阅读(93)  评论(0编辑  收藏  举报