不知道从什么时候开始,在什么东西上面都有个日期,秋刀鱼会过期,肉罐头会过期,连保鲜纸都会过期,我开始怀疑,在这个世界上,还有什么东西是不会过期的。
《重庆森林》
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
如果能帮我点个免费的关注,那就是对我个人的最大的肯定。如果觉得写的还行,分享一下也是我生活的小确幸~
欢迎关注我的公众号