MyBatis 源码解析:架构初探

MyBatis 是一个易用、轻量,且强大的半自动化 ORM 框架,在设计思想和代码实现上都有许多值得我们借鉴的地方,例如动态代理机制的应用,资源文件的加载与解析,缓存模块的设计、反射机制的应用,插件模块的设计,架构分层,以及对设计模式的应用等,是一个非常适合初入源码阅读领域的练手项目。本系列文章将从配置文件解析、映射文件解析,以及 SQL 语句执行机制这三个大方向对整个框架的实现展开分析。本文是本系列的第一篇文章,主要从整体的角度对 MyBatis 的架构设计做一个综述性的介绍。

在正式开始之前,先以一个小例子演示一下 MyBatis 的基本使用。MyBatis 目前已经同时支持 XML 和注解的方式编写 SQL 语句,虽然注解在 Spring 中极大的提升了使用体验,但是对于 MyBatis 而言,个人还是比较倾向于 XML 配置 SQL 语句。下面的示例采用 XML 配置的方式:

<resultMap id="BaseResultMap" type="org.zhenchao.mybatis.entity.User">
    <id column="id" jdbcType="BIGINT" property="id"/>
    <result column="username" jdbcType="VARCHAR" property="username"/>
    <result column="password" jdbcType="VARCHAR" property="password"/>
    <result column="age" jdbcType="INTEGER" property="age"/>
    <result column="phone" jdbcType="VARCHAR" property="phone"/>
    <result column="email" jdbcType="VARCHAR" property="email"/>
</resultMap>

<sql id="Base_Column_List">
    id, username, `password`, age, phone, email
</sql>

<select id="selectByName" parameterType="java.lang.String" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from t_user
    where username = #{name,jdbcType=VARCHAR}
</select>

接下来,我们就可以编写代码基于 MyBatis 执行数据库操作,示例如下:

SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
        .build(Resources.getResourceAsStream("mybatis-config.xml"));
try (SqlSession sqlSession = sessionFactory.openSession()) {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.selectByName("zhenchao");
    // ... use user object
}

这个小例子演示了查询指定名称对应的用户信息的操作,MyBatis 可以基于传递的参数动态生成对应的 SQL 语句。后面的源码分析章节,我们将围绕这个小例子去探究 MyBatis 加载解析资源文件、绑定实参并执行方法对应的 SQL 语句,以及最终返回目标实体对象的过程。下面先对 MyBatis 的运行机制做一个简单的概括,先从整体上对该框架的执行过程有一个感知。

MyBatis 是基于配置的框架,它包含两大类型的配置文件,即 mybatis-config.xml 和 Mapper 接口对应的 SQL 语句配置。这里先约定一下,后面的文章中我们会将前者称为 配置文件,而将后者称为 映射文件。MyBatis 框架在启动时会加载并解析这两大类配置,整个过程对应上述示例中的第一行代码。当完成了对框架的初始化过程,接下来我们就可以创建数据库会话,获取 Mapper 对象并执行目标数据库操作,这一过程可以用下面这幅时序图进行描述:
在这里插入图片描述
SqlSession 是 MyBatis 对外提供的执行数据库操作的统一接口,表示一次数据库会话,所以在具体操作数据库之前需要先开启会话(即获取 SqlSession 对象)。然后需要告知 MyBatis 当前期望操作的具体 Mapper 接口,MyBatis 规定所有的 Mapper 需要定义成接口的形式,这主要是配合 JDK 自带的动态代理机制。MyBatis 会基于动态代理机制为当前 Mapper 接口创建对应的代理对象,并激活对象的 InvocationHandler#invoke 方法。在方法执行过程中判断当前的 SQL 语句类型,并转给 SQL 执行器 Executor 去执行。Executor 先尝试从框架自带的缓存(一级缓存和二级缓存)中获取当前查询对应的结果,如果缓存不命中则会执行数据库操作。对于查询操作而言,数据库返回的结果集与我们期望的实体对象之间还差那么一丢丢,此时,MyBatis 强大的结果集映射处理就可以大显身手,将结果集按照我们的配置映射成为具体的实体类对象(集合)返回。

以上只是大致对框架的运行机制做了一个概括,具体的实现细节后续会用专门的文章进行讲解。下面来看一下 MyBatis 整体的架构设计,如下图所示:
在这里插入图片描述
按照功能进行划分,并参考前人的一些总结,我将 MyBatis 的架构设计分为三层:基础支持层、核心处理层,以及对外接口层。本系列后续的文章中将分别从配置文件解析、映射文件解析,以及 SQL 语句执行机制三个方面对 MyBatis 的实现进行探究,期间会涉及到上图中的各个模块。拟定博文标题如下:
1、MyBatis 源码解析:配置文件的加载与解析
2、MyBatis 源码解析:映射文件的加载与解析
3、MyBatis 源码解析:SQL 语句执行机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值