认识MyBatis核心组件及基本执行流程

本文详细解析了MyBatis的四大核心组件:SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession与SQLMapper的工作原理,以及它们在MyBatis执行流程中的角色。探讨了一级缓存与二级缓存的区别和使用场景。

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

MyBatis的核心组件分为四个部分:

  • SqlSessionFactoryBuilder(构造器):会根据配置或者代码生成SqlSessionFactory,采用的是分步构建的Builder模式.
  • SqlSessionFactory(工厂接口):用它来生成SqlSession,使用的是工厂模式.
  • SqlSession(会话):一个既可以发送SQL执行返回结果,也可以获取Mapper接口.一般我们会让其在业务逻辑代码中"消失".而使用的是MyBatis提供的SQL Mapper接口编程技术,它能提高代码的可读性和可维护性..
  • SQL Mapper(映射器):由一个Java接口XML文件(或注解)构成,需要给出对应的SQL和映射规则.它负责发送SQL去执行,并返回结果.

SqlSessionFactory(工厂接口)

使用MyBatis首先是使用配置或者代码生产SqlSessionFactory,而MyBatis提供了构造器SqlSessionFactoryBuilder(没有成员,只有一堆重载的builder方法,是类,只继承了Object),它提供了一个类Configuration作为引导,采用的是Builder模式.具体的分步则是在Configuration类里面完成的.

通过读取配置文件或者通过Java代码的形式去生成SqlSessionFactory.推荐使用XML形式,因为代码的形式在修改时会比较麻烦.当配置了XML或者提供代码后,MyBatis会读取配置文件,通过Configuration类对象构建整个MyBatis的上下文.SqlSessionFactory是一个接口,在MyBatis中它存在两个实现类:SqlSessionManagerDefaultSqlSessionFactory.一般而言是通过后者来实现的.而前者使用在多线程的环境中,它的具体实现依靠DefaultSqlSessionFactory.

每个基于MyBatis的应用都是以一个SqlSessionFactory的实例为中心的,而SqlSessionFactory唯一的作用就是生产MyBatis的核心接口对象SqlSession.所以他的责任唯一的.我们往往会采用单例模式处理它.

MyBatis中的XML分为两类:

  1. 基础配置文件,通常只有一个,主要是配置一些最基本的上下文参数运行环境;
  2. 映射文件,它可以配置映射关系,SQL,参数等信息.

基础配置文件中可以配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <typeAliases><!--别名-->
        <typeAlias alias="role" type="com.learn.ssm.chapter3.pojo.Role" />
    </typeAliases>
    <!--环境配置,连接的数据库,这里使用的是MySQL-->
    <environments default="mysql">
        <environment id="mysql">
            <!--指定事务管理的类型,这里简单使用Java的JDBC的提交和回滚设置-->
            <transactionManager type="JDBC"></transactionManager>
            <!--dataSource 指连接源配置,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybbs"></property>
                <property name="username" value="root"></property>
                <property name="password" value="root"></property>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--这是告诉Mybatis去哪找持久化类的映射文件,对于在src下的文件直接写文件名,
            如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml-->
        <mapper resource="User.xml"></mapper>
    </mappers>
</configuration>

除非有特殊的需求,才会使用代码创建SqlSessionFactory,比如在配置文件中,需要配置加密过的数据库用户名和密码,需要我们在生成SqlSessionFactory前解密为明文的时候,才会考虑使用这种方式.


SqlSession

SqlSessionMyBatis的核心接口,它有两个实现类:

  1. DefaultSqlSession:单线程使用,
  2. SqlSessionManager:多线程使用

SqlSession类似于一个JDBC中的Connection对象,代表一个连接资源的启用.SqlSession的作用有3个:

  • 获取Mapper接口.
  • 发送SQL给数据库.
  • 控制数据库事务.

SqlSession只是一个门面接口,真正干活的是Executor.

SqlSession获取Mapper接口和发送SQL的功能需要先实现映射器的功能.


SQL Mapper(映射器)

映射器是MyBatis中最重要,最复杂的组件,由一个接口对应的XML文件(或注解)组成.

映射器可以配置以下内容:

  • 描述映射规则.
  • 提供SQL语句,并可以配置SQL参数类型,返回类型,缓存刷新等信息.
  • 配置缓存.
  • 提供动态SQL.

映射器的主要作用就是将SQL查询到的结果映射为一个POJO,或者将POJO的数据插入到数据库中,并定义一些关于缓存等的重要内容.MyBatis运用了动态代理技术为接口生成一个代理对象,代理对象会去处理相关的逻辑.

XML方式创建映射器(推荐):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.RoleMapper">
    <select id="getRole" parameterType="long" resultType="role">
        SELECT id,role_name as roleName,note FROM role WHERE id =#{id}
    </select>
</mapper>

MyBatis在默认情况下提供自动映射,只要SQL返回的列名能和POJO对应起来即可.

注解实现映射器:

这种方式只需要一个接口就可以通过注解来诸如SQL:

package com.mybatis.mapper;
import org.apache.ibatis.annotations.Select;
import com.mybatis.po.Role;
public interface RoleMapper2 {
    @Select("select id,role_name as roleName,note from t_role where id=#{id}")
    public Role getRole(Long id);
}

如果注解和XML同时定义时,XML将会覆盖掉注解方式,推荐使用的是XML方式定义映射器.

使用注解的方式,当SQL语句比较复杂时,会降低代码的可读性,不利于日后的维护和修改.

XML可以相互引入,而注解不可以.

两种发送SQL的方式:

  • 用SqlSession发送SQL
  • 用Mapper接口发送SQL

推荐使用Mapper接口的方式,理由有:

  • 使用Mapper接口编程可以消除SqlSession带来的功能性代码,提高可读性.
  • 使用Mapper接口的方式,IDE会提示错误和校验,而使用SqlSession的方式只有在运行中才能知道是否会产生错误.

生命周期

根据每一个组件的作用去确定其生命周期

SqlSessionFactoryBuilder作用在于创建SqlSessionFactory,创建成功后,就失去了作用,所以它只能存在于创建SqlSessionFactory的方法中,而不要让其长期存在.

SqlSessionFactory可以被认为是一个数据库连接池,它的作用是创建SqlSession接口对象.因为MyBatis的本质就是Java对数据库的操作,所以SqlSessionFactory的生命周期存在于整个MyBatis的应用中.所以一旦创建了SqlSessionFactory,就要长期保存他,直至不再使用MyBatis引用.

  • 如果存在多个数据库连接池会导致数据库连接资源被消耗光,出现系统宕机等情况,所以一般希望SqlSessionFactory作为一个单例,在应用中被共享.

SqlSession相当于一个数据库连接对象,它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让他归还给SqlSessionFactory.

Mapper是一个接口,SqlSession所创建,它的最大生命周期至多和SqlSession保持一致,应该小于等于SqlSession的生命周期.Mapper代表的是一个请求中的业务处理,所以它应该在一个请求中,一旦处理完了相关的业务,就应该废弃它.


MyBatis执行流程:

创建一个SqlSessionFactoryBuilder对象,调用它的duilder方法

  • 该方法会创建XMLConfigBuilder对象读取并解析MyBatis的全局配置文件,,将配置信息封装为Environment对象存储到Configuration对象中,根据配置信息创建SqlSessionFactory对象.
  • XMLMapperBuilder读取并解析映射文件创建MappedStatement对象,将此对象存储在Configuration对象中.
  • SqlSessionFactory是个接口,默认会使用DefaultSqlSessionFactory对象.

使用DefaultSqlSessionFactory对象的openSession方法

  • 该方法会返回一个SqlSession,SqlSession是个接口,默认会返回DefaultSqlSession对象.
  • 每个DefaultSqlSession中有一个Executor成员,Executor接口有四个实现类:
  • 如果使用getMapper方法,会使用动态代理返回一个SqlSession对应的代理对象

Executor会使用StatementHandler来执行SQL语句,而SQL语句对应的是MappedStatement,因此还需将MappedStatement对象传给StatementHandler对象.

执行过程中需要使用ParameterHandler来获取参数,用TypeHandler来处理java数据类型和数据表数据类型之间的映射和转换.

而用ResultSetHandler来处理结果集,期间又会使用到TypeHandler来处理java数据类型和数据表数据类型之间的映射和转换.

以上就是MyBatis的基本执行流程.


MyBatis的一级缓存及二级缓存

MyBatis的一级缓存SqlSession级缓存

  • 每个SqlSession使用各自的缓存.
  • 一级缓存不需要POJO对象可序列化
  • 如果不进行commit,是不会有一级缓存的.
  • 一级缓存默认使用PerpetualCache缓存.

MyBatis的二级缓存SqlSessionFactory级缓存

  • 二级缓存可在多个SqlSession之间共享缓存,因此缓存需要保证线程安全.
  • 二级缓存要求POJO对象可序列化.
  • 二级缓存默认使用SynchronizedCache缓存.

缓存基本执行流程:

执行SQL时首先到缓存中找,如果不存在,访问数据库执行SQL,将查询到的结果放入缓存并将结果返回,如果缓存中有,直接从缓存中取,不访问数据库.期间进行增删改操作会刷新缓存.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值