手写一个迷你版的Mybatis框架

本文将介绍如何手写一个迷你版的Mybatis框架,涵盖了Mybatis的工作原理、核心运行流程,包括初始化阶段、代理阶段和数据读写阶段。在理解Mybatis架构和原理的基础上,逐步实现SqlSessionFactory、SqlSession、Executor等关键组件,实现数据库的读写操作。

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

1. 前言

接触Mybatis框架有些时日了,但我仅仅处于“会使用它”的这个层面,并没有对它进行深入地理解。所以,现在抽时间想对它一探究竟。

2. Mybatis工作原理

Mybatis工作原理参考了此博文:
Mybatis工作原理

2.1 Mybatis架构

2.1.1 Mybatis框架的分层

Mybatis框架大致分为四层:引导层、接口层、数据处理层、框架支撑层。
如下图:
在这里插入图片描述

2.1.2 Mybatis框架的实现原理

Mybatis的底层还是采用了原生JDBC技术来实现对数据库的操作。只是通过 SqlSessionFactory,SqlSession,Executor,StatementHandler,ParameterHandler,ResultHandler和TypeHandler等几个处理器封装了这些过程。
几个组件的功能如下:

  • Executor:执行器(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler:参数处理器(getParameterObject, setParameters)
  • ResultSetHandler:结果处理器(handleResultSets, handleOutputParameters)
  • StatementHandler:sql查询处理器(prepare, parameterize, batch, update, query)

其中,StatementHandler通过ParameterHandler与ResultHandler分别进行参数预编译 与结果处理。而ParameterHandler与ResultHandler都使用TypeHandler进行映射。
在这里插入图片描述

2.2 Mybatis的核心运行流程

Mybatis的核心运行流程可分为三个阶段:

  • 初始化阶段:读取XML配置文件和注解中的配置信息,创建配置对象,并完成各个模块的初始化工作
  • 代理阶段:封装Mybatis的编程模型,使用Mapper接口开发的初始化工作
  • 数据读写阶段:通过SqlSession完成SQL的解析、参数的映射、SQL的执行、结果的反射解析过程

3. 手写Mybatis

按照Mybatis的核心运行流程的三个阶段一步步编码,每完成一个阶段,就进行测试。

3.1 初始化阶段

读取XML配置文件和注解中的配置信息,创建配置对象,并完成各个模块的初始化工作

项目结构图:
在这里插入图片描述

1. MappedStatement
MappedStatement对象是对mapper文件中的每一个标签进行抽象
在这里插入图片描述

@Data
public class MappedStatement {
   
	// 命名空间
    private String namespace;
    // id
    private String resourceId;
    // 返回类型
    private String resultType;
    // sql语句
    private String sql;
}

2. Confifuration
mapper文件中包含多个标签,所有会有个对象来存储标签的集合

Confifuration是用来存储所有配置信息的,且此配置信息全局唯一

/**
 * 存储所有配置信息:
 *      数据库配置信息、mapper配置信息
 */
@Data
public class Configuration {
   
    // jdbc的驱动
    private String jdbcDriver;
    // jdbc的url
    private String jdbcUrl;
    // jdbc的username
    private String jdbcUsername;
    // jdbc的password
    private String jdbcPassword;

    /**
     * mapper文件中可能有多条SQL语句(MapperStatement对象)
     * Map:可实现快速访问
     */
    private Map<String, MappedStatement> mapperStatements = new HashMap<>();
}

3. SqlSessionFactory
我们在使用Mybatis时,会写如下代码:
在这里插入图片描述
在通过工厂模式进行实例化SqlSessionFactory时,会加载mybatis的核心配置文件mybatis-config.xml。所以,这里也仿照mybatis源码,新建个SqlSessionFactory类

public class SqlSessionFactory {
   

    private final Configuration configuration = new Configuration();

    public SqlSessionFactory() {
   
        loadDbInfo();
        loadMappersInfo();
    }
    ...
}

此类有两个作用:

  1. 实例化过程中加载配置文件到Configuration对象
  2. 生产SqlSession对象

loadDbInfo()

// 记录mapper.xml文件存放的位置
public static final String MAPPER_CONFIG_LOCATION = "mappers";
// 记录数据库连接信息文件存放的位置
public static final String DB_CONFIG_FILE = "db.properties";

// 加载数据库配置信息
private void loadDbInfo() {
   
    // 加载数据库信息配置文件
    InputStream dbIn = SqlSessionFactory.class.getClassLoader().getResourceAsStream(DB_CONFIG_FILE);
    Properties p = new Properties();
    try {
   
        // 将配置信息写入到Properties对象
        p.load(dbIn);
    } catch (IOException e) {
   
        e.printStackTrace();
    }

    // 将数据库配置信息写入到Configuration对象
    configuration.setJdbcDriver(p.get("jdbc.driver").toString());
    configuration.setJdbcUrl(p.get("jdbc.url").toString());
    configuration.setJdbcUsername(p.get("jdbc.username").toString());
    configuration.setJdbcPassword(p.get("jdbc.password").toString());
}

loadMappersInfo()

// 加载指定文件夹下的所有mapper.xml文件
private void loadMappersInfo() {
   
    URL resource = null;
    resource = SqlSessionFactory.class.getClassLoader().getResource(MAPPER_CONFIG_LOCATION);
    // 获取指定文件夹信息
    File mappers = new File(resource.getFile());
    if (mappers.isDirectory()) {
   
        File[] files = mappers.listFiles();
        // 遍历文件夹下所有的mapper.xml,并解析信息后,注入到Configuration对象中
        for (File file : files) {
   
            loadMapperInfo(file);
        }
    }
}

loadMapperInfo()
使用dom4j技术对mapper文件进行解析

// 加载指定的mapper.xml文件
private void loadMapperInfo(File file
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值