返回博客列表Back to Blog

MyBatis Dynamic SQL 避坑指南

2026-06-28 · 踩坑记录 · 4 min read

问题背景

在医学指南管理系统项目中,需要实现中英文临床指南的多条件检索:按科室、疾病类型、发布时间、关键词等多维度筛选。传统 MyBatis XML 方式写动态 SQL 会导致 XML 文件膨胀,难以维护。

为什么选 MyBatis Dynamic SQL

MyBatis Dynamic SQL 是 MyBatis 官方推出的 Java DSL 风格的 SQL 构建库,优势在于:

  • 类型安全,编译期检查
  • 无需 XML 配置文件
  • 方法链式调用,可读性好
  • 自动规避 SQL 注入风险

核心实现

依赖配置

<dependency>
    <groupId>org.mybatis.dynamic-sql</groupId>
    <artifactId>mybatis-dynamic-sql</artifactId>
    <version>1.5.0</version>
</dependency>

多条件检索

public List<Guideline> searchGuidelines(SearchDTO dto) {
    SelectStatementProvider select = select(
        id, title, department, publishDate, language
    )
    .from(guidelineTable)
    .where(id, isNotNull())
    .and(title, isLike("%" + dto.getKeyword() + "%")
        .filter(ks -> StringUtils.hasText(dto.getKeyword())))
    .and(department, isEqualTo(dto.getDepartment())
        .filter(ds -> StringUtils.hasText(dto.getDepartment())))
    .and(language, isEqualTo(dto.getLanguage())
        .filter(ls -> StringUtils.hasText(dto.getLanguage())))
    .orderBy(publishDate.descending())
    .build()
    .render(RenderingStrategies.MYBATIS3);

    return client.selectMany(select);
}

.filter() 方法是关键:只有当条件成立时,对应的 WHERE 子句才会被拼入 SQL,相当于 XML 中的 <if test="...">

踩坑记录

坑 1:LIKE 查询的百分号位置

MyBatis Dynamic SQL 的 isLike 不会自动添加 %,需要手动拼接。建议封装工具方法。

坑 2:IN 查询的参数绑定

使用 isIn 时,空集合会导致 SQL 语法错误。务必在调用前检查集合是否为空:

.and(id, isIn(dto.getIds())
    .filter(ids -> ids != null && !ids.isEmpty()))

坑 3:FULLTEXT 全文索引的使用

对于文章标题和正文的全文搜索,使用 MySQL FULLTEXT 索引比 LIKE 快 10 倍以上:

ALTER TABLE guideline ADD FULLTEXT INDEX ft_title_content (title, content);

总结

MyBatis Dynamic SQL 总体来说是一个优秀的库,类型安全的 DSL 确实比 XML 维护性好很多。但在复杂关联查询场景下,XML 的可读性可能更好——关键是根据场景选择合适的工具。