为什么我又写了一个 ORM 框架(MyBatisGX)

为什么我又写了一个 ORM 框架(MyBatisGX)

ORM 的"铁三角诅咒"

写了十年 Java,持久层框架一直没找到理想的选择。

选 MyBatis?

灵活归灵活,但增删改查、分页、批量操作全得手写 XML。每个表都要写一遍,机械重复的工作量很大。

选 MyBatis Plus?

开始用的时候确实爽,慢慢就发现不对劲:

  • 在 Service 层拼 LambdaQueryWrapper,业务代码里到处都是数据库字段名
  • 后来我在 Dao 写 default 方法封装 Wrapper。service 是干净了,但 dao 里全是样板代码,问题只是挪了个地方
  • 简单的 1:1 关联查询也得手写 SQL 或者查两次
  • 批量插入/更新又要继承接口又要继承类,用起来很麻烦

选 JPA?

写代码的时候确实省心,出问题就头疼了。不知道哪里又偷偷执行了一条 SQL,Specification 写动态查询像在用 Java 翻译 SQL 语句。N+1 查询、分页数据爆炸这些坑踩过几次就不想再碰了。复杂点的报表查询?还是老老实实写原生 SQL。

这三个框架分别代表了持久层的三个方向:

  • 要灵活 → 写得累
  • 要省事 → 架构糊
  • 要自动 → 黑盒坑

MyBatisGX 的做法:定义查询,不实现查询

MyBatisGX 的核心思路:查询是稳定的业务能力,不是临时拼出来的实现细节。

Service 层只写业务流程,查询逻辑全部收敛到 Dao 层,用方法定义清楚地表达出来。

方法名查询

java 复制代码
// 简单查询
List<User> findByNameLike(String name);

// 复杂条件
List<User> findByNameLikeAndAgeBetweenOrStatusEq(
    String name, Integer minAge, Integer maxAge, Integer status
);

// 支持任意分组(用括号)
@Statement(value = "findByNameLikeAnd(AgeOrSex)", language = StatementLanguage.METHOD)
List<User> findByNameLikeAndAgeOrSex(String name, Integer age, Integer sex);

方法名就是查询语义,不用 Wrapper,Service 里也不用拼条件。

查询实体

条件太多的时候方法名会很长,这时候用 QueryEntity:

java 复制代码
@QueryEntity
public class UserQuery extends User {
    private String nameLike;      // 自动解析成模糊查询
    private List<Long> idIn;      // 自动解析成 IN 查询
    private List<Long> ageBetween; // 自动解析成 BETWEEN
}

// Dao 层
List<User> findList(UserQuery query);

查询条件作为结构化对象传递,类型安全,IDE 有提示。Service 层不用关心字段名和查询逻辑。

动态查询

加个 @Dynamic 注解,自动生成动态 SQL:

java 复制代码
@Dynamic
List<User> findByNameLikeAndId(String name, Long id);

参数为 null 的时候,条件自动不加入 SQL。

关联查询

java 复制代码
@Entity
public class User {
    @OneToOne(mappedBy = "user", fetch = FetchType.EAGER)
    @Fetch(FetchMode.BATCH)  // 批量抓取,解决 N+1
    private UserDetail userDetail;
    
    @ManyToMany(mappedBy = "userList", fetch = FetchType.LAZY)
    @Fetch(FetchMode.JOIN)   // JOIN 抓取,分页不爆炸
    private List<Role> roleList;
}

不用写 ResultMap,不用手写 JOIN SQL。支持 4 种抓取策略:SIMPLE / BATCH / JOIN / NONE,按场景选。

批量操作

业务开发里批量插入/更新/删除太常见了。导入功能、数据同步、批量审核,到处都要用。

MyBatisGX 直接内置了批量方法:

java 复制代码
// 继承 SimpleDao 就有,不用继承额外的接口或类
int insertBatch(List<User> users);         // 批量插入
int updateBatchById(List<User> users);     // 批量更新
int deleteBatchById(List<Long> ids);       // 批量删除

框架提供的不够?用 @BatchOperation 自己定义:

java 复制代码
@BatchOperation
int insertBatchCustom(@BatchData List<User> users, @BatchSize int batchSize);

不用为了批量功能改架构,直接在 Dao 层调用。


是 JPA 的换皮吗?

不是。

MyBatisGX 确实用了 JPA 的注解(@Entity@OneToMany 等),但只用来描述结构,不参与行为控制。

JPA 有的东西,MyBatisGX 都没有:

  • EntityManager、Session 生命周期
  • 持久化上下文(Persistence Context)
  • 隐式 SQL 执行、脏检查、自动 Flush

MyBatisGX 的执行模型是 MyBatis:

  • SQL 预生成(启动时扫描 Dao,生成 MappedStatement)
  • SQL 可被 mapper.xml 完全接管
  • SQL 最终形态对开发者可见、可干预

厌恶 JPA 的黑盒运行时,但认可它对象建模的成熟设计?MyBatisGX 就是这个定位。


XML 兜底

框架生成的 SQL 有问题?需要写复杂的报表查询?

直接按 MyBatis 原始方式写 XML,框架立即失效。

xml 复制代码
<select id="findByNameLike" resultType="User">
    SELECT * FROM user WHERE name LIKE #{name}
</select>

只要 mapper.xml 里有同名方法,MyBatisGX 就不再自动生成。

优先级:mapper.xml > MyBatisGX 自动生成。

这是个渐进式框架:

  • 简单场景,零 XML
  • 复杂场景,随时接管
  • 无缝兼容现有 MyBatis 项目

还有几个真香的点

无缝升级现有 MyBatis 项目

原来的 mapper.xml 完全不用动,换个依赖、继承个 SimpleDao 接口,就能开始用。

逻辑删除、乐观锁、审计字段

加个注解就行:

java 复制代码
@LogicDelete
private Integer deleted;

@Version
private Integer version;

@GeneratedValue(InputTimeValueProcessor.class)
private LocalDateTime createTime;

复合主键、字段加密、投影 DTO

都支持,不需要复杂配置。


总结

MyBatisGX 不是要替代谁,它回答的是这个问题:

在意代码边界、架构演进和长期维护成本的时候,有没有更好的选择?

只追求"写得快",现在的 ORM 够用。但如果已经被重复代码、架构腐烂、SQL 黑盒、Specification 折磨过,可能不是缺框架,是缺一套正确的抽象。


核心理念: 定义查询,不实现查询。让持久层回归持久层。

相关推荐
无忧智库3 小时前
企业数字化的“底层逻辑”:深度解构4A架构中的数据基石(PPT)
分布式·微服务·架构
钝挫力PROGRAMER3 小时前
关于软件架构的一些疑惑
微服务·云原生·架构
昵称为空C3 小时前
在复杂SpringBoot项目中基于hutool实现临时添加多数据源案例
spring boot·后端
jinanwuhuaguo3 小时前
OpenClaw 2026年4月升级大系深度解读剖析:从“架构重塑”到“信任内建”的范式跃迁
android·开发语言·人工智能·架构·kotlin·openclaw
金融数据出海4 小时前
韩国股票 API 对接指南 Seoul&KOSDAQ
后端
geovindu4 小时前
go: Simple Factory Pattern
开发语言·后端·设计模式·golang·简单工厂模式
咕白m6254 小时前
Python 高效添加与管理 Excel 工作表
后端·python
xingyuzhisuan4 小时前
从x86到Arm:GPU服务器CPU架构多元化趋势深度解读
服务器·arm开发·架构·gpu算力
计算机学姐4 小时前
基于SpringBoot的房屋交易系统
java·vue.js·spring boot·后端·spring·intellij-idea·mybatis