我很好奇之Mybatis Sql执行原理

  • MyBatis深入学习

做了这么久的大自然搬运工,也确实该静下心来好好研究一下之前学过的东西。

MyBatis通过xml配置或注解的方式将要执行的statement(statement、preparedStatemnt、

CallableStatement)进行配置,通过java对象和statement中的sql进行映射生成最终执行的sql语

句,最后由mybatis框架的excute()执行sql并将结果映射成java对象返回。

  • 关于原生JDBC一些问题(纯吐槽)

首先,数据库连接的频繁创建和资源释放,造成系统资源浪费不说,原生API也确实用

起来,让人头疼。

其次,通常情况下,sql语句在程序中以硬编码的形态存在有木有,大大增加了程序的

耦合性(干[no]得[zuo]漂[no]亮[die]),而实际在我们日常开发中,程序中的sql语句的变化

频繁程度,说多了都是泪。

而在使用prepareStatement,一大堆的setString()、setXX(),纯粹硬编码有木有?同时,

在sql语句中的条件也会随着sql的改变而改变,这样还是需要修改代码,增加了系统的维护成本。

在对结果集的封装也存在硬编码(查询列名), sql变化也会导致数据封装跟着变化,而我们理想

的方式,是直接从数据库中查询出来就能够封装成POJO对象。

  • 关于Hibernate与Mybatis的区别

作为两个同样是用来解决数据持久层问题的框架,这里不做评论,只不过它们基于不同的关注点来实现数据持久层解决方案,各有各的优点。但在需求变化迅速的今天,可能更偏向于使用Mybatis吧。下面罗列一些关于两个框架的优缺点,仅作参考。

Hibernate与Mybatis的区别
编号 Hibernate Mybatis
1 完全的ORM框架 不完全的ORM框架
2 提倡使用HQL语句 写SQL语句
3 数据库移植性较好

数据库迁移,只需要改一下数据库方言(dialect)和数据库连接,再修改一下jar包即可。

可移植性较差
4 适合传统项目、目标比较明确、各表相互关系比较复杂的。 适合业务需求变化较快的项目,只需要修改SQL就可
5 在执行效率上来说,Hibernate的效率要略逊一筹,因为Hibernate在默认情况下,会附带查询一些关联,却又不是我们所需要的数据。 根据查询需求定制sql,从技术上来说效率要快不少

好了,关于Hibernate就不在这里继续深究,回到主题。

  • 关于MyBatis的架构

下面,来分析一下它的架构是怎么回事

  1. MyBatis配置:SqlMapConfig.xml

首先,这个文件非强制命名,但是作为一名程序猿,还是遵循行业规则办事才不会被老大骂

。作为MyBatis的全局配置文件,其中配置了MyBatis的运行环境信息,

而该配置文件需要遵循以下配置规则(有顺序要求):

  • properties        (属性)
  • settings             (全局配置参数)
  • typeAliases       (类型别名)
  • typeHandlers   (类型处理器)
  • objectFactory   (对象工厂)
  • plugins               (插件)
  • environments   (环境集合属性对象)
    • environment    (环境子属性对象)
      • transactionManager(事务管理)
      • dataSource                  (数据源)
  • mappers            (映射器)

2.SqlSessionFactory  (产生SqlSession的工厂类)

通过SqlSessionFactoryBuilder的build(…)方法,通过传入一个指SqlMapConfig.xml配置文

件路径的流对象,可以获得到SqlSessionFactory对象, 以获得SqlSession会话。

3.SqlSession (数据库会话对象)

通过SqlSessionFactory获得,相当于Hibernate中的Session对象,用来建立数据库连接。

4.Executor (执行器)

Executor是接口,是对于Statement的封装。真正执行sql是在Excutor中。

下面举个例子:

 

在上面程序中,我们通过SqlSessionFactory调用了openSqlSession(),获得一个SqlSession对象,以下为源码:

而在openSqlSession() 中又调用了openSessionFromDataSource()方法,返回一个SqlSession的实现类对象

DefaultSqlSession,继续上源码:

分析以上源码,可以看出首先是从configuration获取Environment,接着创建Transaction,

最后通过 configuration.newExecutor创建Executor。

DefaultSqlSession中CRUD操作,其实都是在调用Executor接口中的方法执行sql语句 。

Mybatis对外统一提供了一个操作接口类Executor,提供的接口方法有:

update、query、flushStatements、commit、rollback等方法。

然而,实际执行的是该接口实现类中的方法,具体实现类有:

a.抽象类BaseExecutor
b.实现类CachingExecutor
c.实现类BatchExecutor
d.实现类ReuseExecutor
e.实现类SimpleExecutor

 5.MappedStatement(对sql执行参数、结果集的定义)

该对象也是MyBatis的底层封装对象,它包装了MyBatis配置信息以及sql的映射

信息。并且,mapper.xml文件中一个sql对应了一个MappedStatement对象,sql的id就是MappedStatement的id。同时,它还对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,  Executor通过MappedStatement在执行sql前,将输入的java对象映射至sql中。

同时,MappedStatement对sql执行输出结果集也进行定义,将结果映射至java对象。

发表评论

电子邮件地址不会被公开。