《MyBatis技术内幕》读书笔记

这篇博客是对《MyBatis技术内幕》的简单概述,介绍了ORM框架的作用,对比了Hibernate、JPA、Spring JDBC和MyBatis的特性。重点讨论了MyBatis的快速入门,包括其整体架构,强调了MyBatis的灵活性和性能,如动态SQL和自定义映射,以及其一级和二级缓存机制。虽然没有深入源码分析,但概述了MyBatis的使用方式和主要组件,适合初学者了解MyBatis。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

看这本书的初衷,只是想大概了解一下MyBatis的工作方式,大概了解一下原理。这本书是从源码出发进行讲解的,对每个模块都进行了细致的介绍。

在现阶段,个人对源码分析不是那么感兴趣,因为通常源码分析都是从已经很熟悉源码的人的角度出发,像cpu似的疯狂进入xx函数,这个函数又进入了xx函数,强调了很多细节问题,感觉在做十字绣,但是却没法对框架的构造有整体的把握

当然,从分析源码的角度看,这本书还是挺好的,各个模块也是平行的,铺开来用不同的章节讲,脉络也比较清晰——只不过,我想把仅有的时间用来了解更有趣的知识

所以,这篇文章其实只有MyBatis(包括ORM框架)的简单介绍,后续的源码分析是没有的,也许以后做了相关工作,就会再去深入了解吧

1.MyBatis快速入门

1.1 ORM简介

ORM(Object Relational Mapping,对象-关系映射)框架是为了方便解决程序中业务逻辑和数据库操作交互的问题。

具体来说,在系统开发的过程中,开发人员需要使用面向对象的思维实现业务逻辑,而设计数据库表或操作数据库时,需要通过关系型的思维方式思考问题。应用程序与关系型数据库的交互,就是数据在程序对象和关系结构中表、列、字段之间的转换。

简单来说,向数据库发起请求时,需要将Java对象(程序中的对象,因为主要是Java开发环境,所以这两个概念会互用)转化成SQL语句里的参数;数据库返回数据时,要将数据库里的一行数据,映射到一个Java对象,方便程序后续的读取。

JDBC是Java与数据库交互的统一API。实际上它分为两组API,一组是面向Java应用开发者的API,一组是面向数据库驱动程序开发人员的API。前者是一个标准的Java API且独立于各个厂家的实现,后者则是前者的底层支持,不同的数据库产品有不同的实现。

进行Java开发时,可以通过JDBC完成多种数据库操作。例如,发起一次查询操作时,有如下几个步骤

1.注册数据库驱动类,指明数据库URL 用户名 密码;
2.打开数据库连接;
3.通过数据库连接创建statement对象(可以认为是写明SQL语句),这一过程中需要进行基础语句创建、Java对象参数插入;
4.通过statement对象执行SQL语句,得到ResultSet对象;
5.通过ResultSet读取数据,并将数据转换成Java对象;
6.关闭ResultSet、Statement、数据库连接,释放相关对象。

可以看到,在执行一次查询的操作中,只有操作35和实际业务有关,因此1246的操作都是重复性的,可以进行封装。

再看操作5,将数据转换成Java对象这一步可能也可以封装,比如执行多种条件范围的查询,返回的对象都是一样的,那也可以将操作5抽象成一个映射函数,取出ResultSet中的每一行,将每一列都给一个Java对象的某个字段赋值

再看操作3,JDBC中创建Statement对象,需要手工拼接字符串,并且手动将参数一个一个插入,这对于开发人员来说也是十分痛苦的(因为要疯狂敲 ‘?’ 号来做参数的占位符,数得眼花,还特别容易数错,还得用很多的 ‘+’ 来拼接字符串,编写出的SQL语句非常不直观),有没有办法能让我们指定数据库里表的每一列与Java对象字段的对应关系,并且自动帮我们映射过去呢?

于是,ORM框架出现了。它封装了重复的代码,用户可以根据配置文件指明Java对象字段到数据库列名的相互对应,此外还具有缓存、连接池等额外功能来提升数据库性能。

因此,在开发中大型项目时,优先考虑ORM框架来实现DAO(Data Access Object,数据访问对象)层。

1.2 常见持久化框架

Hibernate

H除了能实现ORM框架的功能之外,可以帮助开发人员屏蔽不同数据库产品中SQL语句的细微差别(不同的数据库,对SQL标准支持、内置的函数并不完全相同。同样的SQL语句可能在一种数据库中执行成功,但是在另一种数据库里执行报错),这是其突出的特性。

H提供了HQL语言、以及Criteria API等对SQL语句进行封装(H封装了数据库层面的所有操作),开发人员完全不用自己编写SQL语句,因此程序的可移植性也大大提高了。

但是H的劣势也在于全自动化的映射方式,使得开发人员难以对SQL语句进行优化(如控制索引的使用等),因此后来出现了iBatis(MyBatis的前身)这种半自动化的映射方式来解决性能问题。

JPA

是EJB3.0中的持久化规范,但是实际上没有得到广泛应用

Spring JDBC

Spring对JDBC的简单封装,封装了重复代码,但是没有提供映射配置、缓存等额外功能。

MyBatis

MyBatis能完成ORM的功能。其配置文件不但能指明映射关系,还可以编写动态SQL语句,MyBatis可以根据执行时传入的参数拼凑出完整的SQL语句,免去了手动拼SQL语句的痛苦。

同时,还具有缓存、连接池等额外功能。

总结

从介绍的三种(JPA只是规范,不是框架)ORM框架来看,可以从几个方面来选择合适的ORM框架:

性能:Spring JDBC&Mybatis直接使用原生SQL语句,优化空间很大;Mybatis Hibernate有设计良好的缓存机制

灵活性:三者都可以与第三方数据源配合使用

可移植性:H屏蔽了底层数据库方言,但是实际项目中,也几乎不会来回切换数据库。

开发效率:Mybatis Hibernate都提供了XML映射配置和注解实现映射。

1.3 MyBatis示例

以一个简单的Mapper XML配置文件和一段经典的应用代码为例,展示MyBatis的使用方式。从它的使用中,就能深刻领会到ORM框架的好处(如果之前做过JDBC编程的话)。

<mapper namespace="com.xxx.AuthorMapper">
    <!--下面定义了结果集到java对象的映射关系,需要给这个映射取个名字并指定返回的java对象的类名-->
    <resuleMap id="authorResult" type="Author">
        <id property="id" column="author_id"/>
        <result property="username" column="username"/>
        <!--....略去其它的属性映射-->
    </resuleMap>

    <!--下面定义了SQL语句(以下也称为SQL节点),以一个select节点为例。需要指定语句名称以及结果的映射方式)-->
    <select id="selectAuthorDetails" resultMap="authorResult">
        SELECT A.username FROM Author WHERE A.id = #{id};
    </select>
</mapper>
public class Main {
    public static void Main(){
        String configFilename = "xxx.xml";
        InputStream is = Resources.getResourceAsStream(configFilename);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = sqlSessionFactory.openSession();
        try {
            Map<String, Object> parameter = new HashMap<>();
            // 这里放入查询需要的参数。由上面的XML文件中可以看到selectBlogDetails语句只需要id属性,因此放入id属性。
            parameter.put("id", 1);
            // 指定操作的mapper对象,这个mapper对象的配置参见上面的XML文件。
            // 实际上,还可以通过将Mapper和接口绑定的方式来调用SQL语句,这在后面会进一步说明(Binding模块)
            Blog blog = sesison.selectOne("com.xxx.BlogMapper.selectBlogDetails", parameter);
            // ...后续对blog对象的操作
        } finally {
            session.close();
        }
    }
}

1.4 MyBatis整体架构

主要分为三层,基础支持层,核心处理层,接口层。

在这里插入图片描述

1.4.1 基础支持层

反射模块

对Java的原生反射进行封装,封装了获取MyBatis使用中需要得到的JavaBean信息等一系列操作

类型转换模块

实现JDBC类型与JAVA类型之间的转换。不论是执行SQL语句时将Java对象实参转化成JDBC类型,还是返回的结果从JDBC类型转换成Java对象,都需要这个模块支持

日志模块

继承了多种第三方日志框架(显然,适配器模式)

资源加载模块

提供了加载类和加载其他资源的功能。

解析器模块

对XPath(一个解析XML文件的库)进行封装,也就是解析XML配置文件;另一方面,要对解析SQL语句进行支持

数据源模块

数据源主要负责管理数据库连接等,对ORM框架的影响很大。

事务管理

MyBatis提供了事务接口和简单实现。在很多场景中,MyBatis会与Spring进行继承,由Spring框架管理事务

缓存模块

缓存是优化数据库时最有效的手段之一。这样对于相同的请求,可以直接返回结果,而不用经过数据库,大大减轻数据库的压力。

MyBatis提供一级缓存和二级缓存,前者缓存每个SqlSession中的语句执行结果;后者缓存应用执行至今所有的执行结果。

需要注意的是:MyBatis自带的这两级缓存和JVM共享内存,如果缓存较大,则会影响系统中其它部分的运行。如果需要缓存大量数据时,优先考虑Redis Memcache等产品。

Binding模块

在前面的示例中可以看到,调用SqlSession响应方法执行数据库操作时,需要指定映射文件中定义的SQL节点。如果出现拼写错误,则要运行时才能发现异常。为了尽早发现错误,引入了Binding模块,将用户自定义的Mapper接口与映射配置文件关联起来,代码中通过调用Mapper接口的方法执行相应SQL语句(实际上是MyBatis帮我们生成了动态代理对象)完成数据库操作。

1.4.2 核心处理层

配置解析

加载配置文件、映射配置文件、Mapper接口中的注解信息,形成相应的对象并保存到Configuration对象中。

如节点会被解析为ResultMap对象;节点会被解析为ResultMapping对象等。

之后,利用该Configuration对象创建得到SqlSessionFactory对象,获取对应的SQL语句进行执行。

SQL解析与scripting模块

解析Statement对象、绑定用户实参,实现动态SQL语句(如 等节点)的功能。

SQL执行

涉及多个组件,包括SQL实参绑定、执行SQL语句得到结果集、结果集映射这三大步骤,还涉及到事务管理、缓存管理等功能

插件

用户可以自定义插件对MyBatis进行扩展。

1.4.3 接口层

核心是SqlSession接口,定义了上层与Mybatis的交互方式。接口层收到调用请求时,会调用核心处理层的相应模块完成具体的数据库操作。

后续章节

快速地浏览了后续章节,发现主要都是源码分析(在现阶段,个人对源码分析不是那么感兴趣,因为通常源码分析都是从已经很熟悉源码的人的角度出发,像cpu似的疯狂进入xx函数,这个函数又进入了xx函数,强调了很多细节问题,但是却没法对框架的构造有整体的把握),而最重要的MyBatis的优势和原理已经基本清楚,因此不再分析,转战其他书籍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值