【0~1】实现一个精简版的Mybatis框架

不知道从什么时候开始,在什么东西上面都有个日期,秋刀鱼会过期,肉罐头会过期,连保鲜纸都会过期,我开始怀疑,在这个世界上,还有什么东西是不会过期的。

《重庆森林》

01 Mybatis介绍

MyBatis是一个优秀的Java轻量级持久层框架,它封装了JDBC,使开发人员只需要关注SQL语句本身,而不需要处理繁琐的JDBC步骤。

核心功能和特点

  • 简单易学:MyBatis配置和使用相对简单,开发者可以通过XML或注解的方式定义SQL语句,与数据库进行交互。
  • 灵活强大:支持动态SQL、存储过程调用以及复杂的映射关系,能够满足各种不同的数据库操作需求。
  • 性能优异:通过合理的配置和优化,可以实现高效的数据访问和操作,提升应用的整体性能。
  • 与Spring等框架无缝集成:方便在企业级应用开发中与其他主流框架协同工作,构建完整的应用架构。
  • 定制化SQL:支持编写自定义SQL、存储过程以及高级映射。
  • 事务处理:提供了简单的事务处理接口,可以方便地进行事务管理。
  • 缓存机制:提供了缓存机制,可以提高数据库查询性能。

工作原理

MyBatis的工作原理基于一个全局配置文件和多个映射文件。它使用SqlSessionFactoryBuilder构建SqlSessionFactory,然后通过SqlSessionFactory创建SqlSession对象,SqlSession提供了操作数据库的方法,通过调用执行器来操作mapperStatement对象执行SQL语句,返回结果。

核心组件

  • SqlSessionFactoryBuilder:根据配置信息生成SqlSessionFactory。
  • SqlSessionFactory:依靠工厂生成SqlSession。
  • SqlSession:可以发送SQL执行并返回结果,也可以获取Mapper接口。
  • SQL Mapper:由一个JAVA接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则。

使用方式

  • 配置文件:创建mybatis配置文件,定义数据源和映射器。
  • 映射文件编写:编写映射文件,定义SQL语句和映射规则。
  • 创建SessionFactory和Session:通过配置文件创建SqlSessionFactory,然后创建SqlSession。
  • 执行操作:通过SqlSession执行CRUD操作,并提交事务。

优点

  • 减少代码量:与JDBC相比,减少了50%的代码量。
  • SQL代码分离:SQL代码从程序代码中彻底分离出来,可以重用。
  • 动态SQL支持:提供XML标签,支持编写动态SQL。
  • ORM字段关系映射:提供映射标签,支持对象与数据库的ORM字段关系映射。

缺点

  • SQL语句编写工作量大:需要开发人员掌握XML文件编写,且数据库移植性比较差。

MyBatis作为一个半自动化的ORM框架,提供了一种简单且强大的方式来与关系型数据库进行交互,适用于各种规模的Java应用程序。

02 手写Mybatis

基于第一小节的介绍,我们可以这样结合 Spring 一步步从0~1实现一个精简版的mybatis。

1. 读取配置文件

使用 DOM4J 或 SAX 解析 XML 文件,例如 mybatis-config.xml,提取以下信息:

  • 数据库连接配置(如 driver, url, username, password
  • Mapper 映射文件路径

示例代码如下:

public class ConfigParser {
    public static Configuration parseConfig(String configFile) {
        // 解析 XML 文件并初始化 Configuration 对象
    }
}

2. 读取 Mapper 文件

Mapper 文件是 SQL 和 Java 方法的映射关系,可以用 DOM4J 解析:

  • 将 SQL 语句(<select><insert> 等)绑定到特定接口的方法。
  • 存储到 MappedStatement 对象中,供执行时使用。

3. 创建 SqlSessionFactory

SqlSessionFactory 是 MyBatis 的核心入口。需要初始化以下内容:

  • 数据库连接池(如 HikariCP)。
  • 解析后的配置文件内容。
  • 映射关系。
public class SqlSessionFactory {
    private Configuration configuration;

    public SqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    public SqlSession openSession() {
        return new DefaultSqlSession(configuration);
    }
}

4. 实现 SqlSession

SqlSession 是执行数据库操作的接口。内部使用 JDBC 封装查询、插入等操作。

 public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    public <T> T selectOne(String statement, Object parameter) {
        // 执行单条查询
    }

    public int insert(String statement, Object parameter) {
        // 执行插入操作
    }
}

5. 动态代理 Mapper

使用 JDK 动态代理生成接口的实现类:

  • 拦截方法调用,通过 MapperProxy 查找对应的 SQL 并执行。
  • 返回执行结果。
 public class MapperProxy implements InvocationHandler {
    private SqlSession sqlSession;

    public MapperProxy(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    public Object invoke(Object proxy, Method method, Object[] args) {
        // 根据方法找到对应的 SQL 并执行
    }
}

public class MapperFactory {
    public static <T> T getMapper(Class<T> clazz, SqlSession sqlSession) {
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(),
                                          new Class[]{clazz},
                                          new MapperProxy(sqlSession));
    }
}

03 后续优化与拓展

1. 支持事务

使用 ThreadLocal 管理事务状态。

2. 增加一级/二级缓存

实现查询结果的缓存机制。

3. 动态 SQL

解析 <if><foreach> 等动态 SQL 标签。

4. 插件机制

实现类似 MyBatis 的 Interceptor,允许用户自定义行为

04 总结

行文(阅读)至此,我们大概可以知道自定义mybatis的本质可以概括为以下3步:1、解析xml配置文件(拿配置);2、将mapper接口与mapper配置文件做映射,包括方法名、方法返回值、方法参数以及sql语句(做映射);3、通过代理执行mapper接口的对应方法(执行 SQL)

详细具体带注释的代码在Github:https://github.com/JeffrayZ/my-mybatis

PS:这大概率是2024年我写的最后一篇公众号文章了,谢谢你们一直的支持和陪伴。🎄祝大家圣诞节快乐🎉朋友们,我们明年再见~

Love & Peace & Thanks

如果能帮我点个免费的关注,那就是对我个人的最大的肯定。如果觉得写的还行,分享一下也是我生活的小确幸~

欢迎关注我的公众号
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值