1 mybatis
1.1 ORM框架
传统的数据库连接,软件程序和数据库交互的过程需要建立连接、拼装和执行SQL、转化操作结果等步骤,相对比较繁琐。拼装SQL和转化结果十分繁琐。
面向对象是在软件工程原则(如聚合、封装)的基础上发展起来的,而关系型数据库则是在数学理论(集合代数等)的基础上发展起来的,两者并不是完全匹配的,它们中间需要信息的转化。
这样的转化称为对象关系映射(Object Relational Mapping,简称 ORM、O/RM或 O/R mapping)。ORM 会在数据库数据的读取和写入操作过程中频繁发生,为了降低这种转化过程的开发成本,产生了大量的 ORM框架,MyBatis就是其中非常出色的一款。
MyBatis没有将 Java对象和数据表直接关联起来,而是将 Java方法和 SQL语句关联起来。这使得 MyBatis在简化了 ORM操作的同时,也支持了数据表的关联查询、视图的查询、存储过程的调用等操作。除此之外,MyBatis 还提供了一种映射机制,将 SQL语句的参数或结果与对象关联起来。 MyBatis的核心功能。
- 将包含 if等标签的复杂数据库操作语句解析为纯粹的 SQL语句。
- 将数据库操作节点和映射接口中的抽象方法进行绑定,在抽象方法被调用时执行数据库操作。
- 将输入参数对象转化为数据库操作语句中的参数。
- 将数据库操作语句的返回结果转化为对象。
使用 MyBatis时,只要调用一个方法就可以执行一条复杂的 SQL语句。在调用方法时可以给方法传递对象作为 SQL语句的参数,而 SQL语句的执行结果也会被映射成对象后返回。因此,关系型数据库被 MyBatis屏蔽了,读写数据库的过程成了一个纯粹的面向对象的过程。除核心映射功能外,MyBatis 还提供了缓存功能、懒加载功能、主键自增功能、多数据集处理功能等。
2. 概述
2.1 pom文件中引入依赖
mybatis还支持完全代码配置、基于XML的配置和外部框架配置。
引入mybatis-spring-boot-starter, 这里不仅引用了 mybatis包,还引用了 mybatis-spring、mybatis-spring-boot-autoconfigure等包。使用starter,可以省略mybatis的配置文件,只需要创建映射文件即可。
2.2 配置文件 mybatis-config.xml
MyBatis的配置文件 mybatis-config.xml。该 XML文件的根节点为 configuration,根节点内可以包含的一级节点及其含义:
- properties:属性信息,相当于 MyBatis的全局变量。
- settings:设置信息,通过它对 MyBatis的功能进行调整。
- typeAliases:类型别名,在这里可以为类型设置一些简短的名字。
- typeHandlers:类型处理器,在这里可以为不同的类型设置相应的处理器。
- objectFactory:对象工厂,在这里可以指定 MyBatis创建新对象时使用的工厂。
- objectWrapperFactory:对象包装器工厂,在这里可以指定 MyBatis使用的对象包装器工厂。
- reflectorFactory:反射器工厂,在这里可以设置 MyBatis的反射器工厂。
- plugins:插件,在这里可以为 MyBatis 配置差价,从而修改或扩展 MyBatis 的行为。
- environments:环境,这里可以配置 MyBatis运行的环境信息,如数据源信息等。
- databaseIdProvider:数据库编号,在这里可以为不同的数据库配置不同的编号,这样可以对不同类型的数据库设置不同的数据库操作语句。
- mappers:映射文件,在这里可以配置映射文件或映射接口文件的地址。
同时要注意,对配置文件中的一级节点是有顺序要求的,这些节点必须按照上面列举的顺序出现。在使用中可以根据实际需要选择相应的节点依次写入配置文件。
2.3 映射文件
映射文件也是一个 XML文件,用来完成 Java方法与 SQL语句的映射、Java对象与SQL参数的映射、SQL查询结果与 Java对象的映射等。通常,在一个项目中可以有多个映射文件。映射文件的根节点为 mapper,在 mapper节点下可以包含的节点及其含义:
- cache:缓存,通过它可以对当前命名空间进行缓存配置。
- cache-ref:缓存引用,通过它可以引用其他命名空间的缓存作为当前命名空间的缓存。
- resultMap:结果映射,通过它来配置如何将 SQL查询结果映射为对象。
- parameterMap:参数映射,通过它来配置如何将参数对象映射为 SQL参数。该节点已废弃,建议直接使用内联参数。
- sql:SQL语句片段,通过它来设置可以被复用的语句片段。
- insert:插入语句。
- update:更新语句。
- delete:删除语句。
- select:查询语句。
2.4 映射接口文件
映射接口文件是一个 Java接口文件,并且该接口不需要实现类。通常情况下,每个映射接口文件都有一个同名的映射文件与之相对应。在映射接口文件中可以定义一些抽象方法,这些抽象方法可以分为两类:
- 第一类抽象方法与对应的映射文件中的数据库操作节点相对应。
- 第二类抽象方法通过注解声明自身的数据库操作语句。当整个接口文件中均为该类抽象方法时,则该映射接口文件可以没有对应的映射文件。
2.5 执行过程
/**
* - SqlSession:代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的会话)
* - SqlSessionFactory:是“生产”SqlSession的“工厂”。
* - 工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类”中,以后都使用这个工厂类来“生产”我们需要的对象。
* @throws IOException
*/
@Test
public void test01() throws IOException {
//1. 读取MyBatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//3. 通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//4.1 创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
//SqlSession sqlSession = sqlSessionFactory.openSession();
//4.2 创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//5. 通过反射生成代理,创建UserMapper接口的代理实现类对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//6. 调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句
List<User> allUser = userMapper.getUserList();
//呼应 4.1 sqlSession.commit();
System.out.println(allUser);
}
在整个数据库操作阶段,MyBatis完成的工作可以概述为以下几条。
- 建立连接数据库的 SqlSession。
- 查找当前映射接口中抽象方法对应的数据库操作节点,根据该节点生成接口的实现。
- 接口的实现拦截对映射接口中抽象方法的调用,并将其转化为数据查询操作。
- 对数据库操作节点中的数据库操作语句进行多次处理,最终得到标准的 SQL语句。
- 尝试从缓存中查找操作结果,如果找到则返回;如果找不到则继续从数据库中查询。
- 从数据库中查询结果。
- 处理结果集。建立输出对象;根据输出结果对输出对象的属性赋值。
- 在缓存中记录查询结果。
- 返回查询结果。
3. 源码结构
按照包的功能,我们将所有的包分成三大类:
- 基础功能包:这些包用来为其他包提供一些外围基础功能,如文件读取功能、反射操作功能等。这些包的特点是功能相对独立,与业务逻辑耦合小。
- 配置解析包:这些包用来完成配置解析、存储等工作。这些包中的方法主要在系统初始化阶段运行。
- 核心操作包:这些包用来完成数据库操作。在工作过程中,这些包可能会依赖基础功能包提供的基础功能和配置解析包提供的配置信息。这些包中的方法主要在数据库操作阶段运行。
基础功能包 | 配置解析包 | 核心操作包 |
-exceptions -reflection -annotations -lang -type -io -logging -parsing | -binding -builder -mapping -scripting -datasource | -jdbc -cache -transaction -cursor -executor -session -plugin |
这些包在整个 MyBatis中的作用。
源码阅读过程中有一个非常重要的技巧,那就是从整个项目的外围源码入手。(外围源码很少依赖核心源码,相对独立。先阅读外围源码,受到其他未阅读部分的干扰较小。核心源码大量依赖外围源码。在阅读核心源码时应确保其涉及的外围源码均已阅读完毕,这样可以降低核心源码的阅读难度。于是整个源码阅读过程会如同剥洋葱一般,由外及内、逐层深入。)MyBatis 源码中,基础功能包是最外围的包,配置解析包位于中间,核心操作包位于内层。