在 Java 后端里,MyBatis 一直有一种很微妙的优势:它不像全自动 ORM 那样把 SQL 藏起来,又能用 Mapper、XML、动态 SQL 把复杂查询管住。MyBatis-Plus 和 Xbatis 都是在这个基础上继续提效的增强框架,只是路线不完全一样:前者胜在成熟生态和工程默认项,后者更强调用更现代、更类型化的方式组织数据访问代码。
两个框架解决的是同一类痛点,但侧重点不同
MyBatis 原生能力足够稳,但在业务项目里经常会遇到重复劳动:
- 每张表都要写基础 CRUD。
- 分页、逻辑删除、乐观锁、字段填充反复配置。
- 条件查询容易散落在 XML 或字符串拼接中。
- 团队成员水平不一致时,Mapper 风格很快分裂。
MyBatis-Plus 的典型价值,是把这些“企业应用里 80% 都会写到的样板代码”沉淀成一套成熟约定。它适合希望快速落地、依赖社区经验、尽量少踩坑的团队。
Xbatis 则更适合关注代码表达力、类型安全、查询构造体验的项目。它同样围绕 MyBatis 生态做增强,但更容易被看作一种“更现代的 Mapper 编写方式”:让 CRUD、条件构造、字段映射等操作尽量贴近 Java 代码本身,而不是把复杂度全部留给 XML 或字符串。
可以粗略记成一句话:
- MyBatis-Plus:成熟、稳定、插件多、社区资料多,适合大多数通用后台系统。
- Xbatis:更关注开发体验和代码化表达,适合愿意接受新框架、追求更清晰查询构造的团队。
选型时不要只看 CRUD,要看团队会怎么写复杂查询
很多 ORM 增强框架演示时都会从 insert、updateById、selectById 开始,但真实项目的分水岭往往不是这些基础操作,而是复杂查询:多条件筛选、动态排序、关联查询、权限过滤、租户隔离、统计报表。
如果团队已经大量使用 MyBatis-Plus,它的优势很明显:
BaseMapper、IService、LambdaQueryWrapper使用广泛,新人容易搜索到答案。- 分页、逻辑删除、乐观锁、多租户等能力有成熟插件或通用实践。
- 与 Spring Boot 项目结合成本低,很多脚手架已经内置。
但它也有边界:当查询越来越复杂时,Wrapper 代码可能变长,XML 也可能重新回到项目中心。此时团队需要明确规范:哪些查询用 Wrapper,哪些查询必须回到 XML 或手写 SQL。
Xbatis 的吸引力在于,它试图让查询表达更贴近 Java 类型系统,减少字符串式字段引用带来的维护成本。对于强调重构安全、字段变更频繁、业务查询组合很多的项目,这类体验会很有价值。不过,新框架通常意味着资料、插件、团队熟悉度都要重新评估。
可以这样实践:用同一张用户表比较代码风格
下面示例不是复刻某个框架的完整生产配置,而是给团队做技术预研时可以改造的最小样例。假设有一张用户表:
CREATE TABLE user_account (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(64) NOT NULL,
status TINYINT NOT NULL,
created_at DATETIME NOT NULL
);
如果你已经在 Spring Boot 项目中使用 MyBatis-Plus,可以用下面这种方式完成常见条件查询。需要把包名、数据源和依赖版本替换成你项目里的配置。
package com.example.demo.user;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
public class UserAccount {
private Long id;
private String username;
private Integer status;
private LocalDateTime createdAt;
public Long getId() { return id; }
public String getUsername() { return username; }
public Integer getStatus() { return status; }
public LocalDateTime getCreatedAt() { return createdAt; }
}
@Mapper
interface UserAccountMapper extends BaseMapper<UserAccount> {
}
@Service
class UserAccountService {
private final UserAccountMapper mapper;
UserAccountService(UserAccountMapper mapper) {
this.mapper = mapper;
}
public List<UserAccount> findActiveUsers(String keyword, int pageNo, int pageSize) {
LambdaQueryWrapper<UserAccount> query = new LambdaQueryWrapper<UserAccount>()
.eq(UserAccount::getStatus, 1)
.like(keyword != null && !keyword.isBlank(), UserAccount::getUsername, keyword)
.orderByDesc(UserAccount::getCreatedAt);
return mapper.selectPage(Page.of(pageNo, pageSize), query).getRecords();
}
}
这个例子的重点不是“代码最短”,而是说明 MyBatis-Plus 的典型工作流:实体类、BaseMapper、Wrapper、分页插件共同完成常见后台查询。
做 Xbatis 预研时,也建议用同一张表、同一组查询条件来写 PoC,而不是只跑官方 hello world。你可以把评估脚本设计成这样:
#!/usr/bin/env bash
set -euo pipefail
# 1. 分别创建两个 Spring Boot 分支:mp-poc 与 xbatis-poc
# 2. 使用同一张 user_account 表
# 3. 实现同样的 5 个接口:新增、按 ID 查询、分页筛选、更新状态、逻辑删除
# 4. 记录每个实现的代码行数、SQL 可读性、IDE 重构体验、测试编写成本
printf "PoC checklist:\n"
printf "- CRUD implementation completed\n"
printf "- Dynamic query readable\n"
printf "- Pagination behavior verified\n"
printf "- SQL log easy to inspect\n"
printf "- New teammate can understand mapper style\n"
更现实的评估方式,是让两名团队成员分别用两个框架实现同一个接口,然后互相 code review。谁的代码更容易读、哪里需要查文档、字段改名时会不会漏改,这些结果比单纯比较功能清单更有价值。
工程维度:成熟度、生态和迁移成本
MyBatis-Plus 的强项是“工程确定性”。它存在时间长,生产案例多,常见坑基本都有人踩过。对于中大型团队,这一点很关键:框架不是只有写代码那一刻才有成本,排查线上问题、升级依赖、招聘新人、接入脚手架都会消耗时间。
Xbatis 的优势更偏向“开发表达力”。如果它的查询模型、实体映射方式和团队代码审美高度契合,长期维护体验可能更舒服。但采用前要认真检查几件事:
- 是否支持你项目里的数据库方言和分页方式。
- 是否能与现有 MyBatis XML、插件、拦截器共存。
- 是否有足够清晰的文档和版本发布节奏。
- 团队是否愿意为更好的代码体验承担学习成本。
- 遇到复杂 SQL 时,是否仍能优雅回退到手写 SQL。
不要把“新”直接等同于“先进”,也不要把“老牌”直接等同于“保守”。选型的核心是业务复杂度、团队经验和维护周期是否匹配。
建议:保守项目选 MyBatis-Plus,体验驱动项目再评估 Xbatis
如果你的项目是典型后台管理、交付周期紧、团队人员流动较大,MyBatis-Plus 通常是更稳的默认选择。它不一定在每个语法细节上最优雅,但社区、插件和排错经验会帮你省下大量隐性成本。
如果你的团队已经对 MyBatis-Plus 的 Wrapper 风格、XML 分裂、字段维护成本感到不满意,并且愿意做 PoC,那么 Xbatis 值得进入候选名单。不要一上来全量替换,可以先挑一个边界清晰的业务模块试点。
落地前可以用这份检查清单:
- 是否能覆盖项目最复杂的 3 类查询。
- 是否支持现有事务、分页、审计字段、逻辑删除方案。
- 是否方便查看最终 SQL 和绑定参数。
- 是否能被 IDE 重构、安全扫描、单元测试友好支持。
- 是否有明确的回退方案,例如保留原生 MyBatis XML 能力。
框架选型不是为了追求代码演示时的漂亮,而是为了让三个月后、三年后的业务代码仍然能被读懂、能被修改、能在事故现场快速定位问题。