Why Fluent MyBatis Outshines MyBatis Plus and JOOQ for Java SQL Building
This article examines the evolution of Java SQL‑mapping frameworks, compares MyBatis, MyBatis Plus, MyBatis Dynamic SQL, JOOQ and the newer Fluent MyBatis, highlights Fluent MyBatis’s code‑centric design, IDE support, dynamic table naming, and provides practical code examples to illustrate its advantages.
Popularity of MyBatis in East Asia
Google Trends shows that MyBatis dominates the Java SQL‑mapping market in East Asia and remains the most popular Java database access framework in China.
From iBatis to Modern Code‑First Solutions
iBatis, created in 2002, relied heavily on XML configuration. Over the years, the community shifted toward code‑first approaches, with MyBatis introducing annotation‑based SQL in 2010 and MyBatis Dynamic SQL embracing full code‑based query construction in 2016.
Emergence of Fluent MyBatis
Fluent MyBatis, launched at the end of 2019 by Alibaba’s technology team, combines the lightweight nature of MyBatis Dynamic SQL with richer features such as automatic code generation, compile‑time enhancements, and seamless IDE assistance.
Implementation Comparison
Fluent MyBatis adopts a mechanism similar to MyBatis Dynamic SQL, using native Provider annotations while generating additional helper classes during compilation. It hides internal details, offering a clean API for developers.
Fluent MyBatis Query Example
// Using Fluent MyBatis to build a query
mapper.listMaps(new StudentScoreQuery()
.select
.schoolTerm()
.subject()
.count.score("count")
.min.score("min_score")
.max.score("max_score")
.avg.score("avg_score")
.end()
.where.schoolTerm().ge(2000)
.and.subject.in(new String[]{"英语", "数学", "语文"})
.and.score().ge(60)
.and.isDeleted().isFalse()
.end()
.groupBy.schoolTerm().subject().end()
.having.count.score.gt(1).end()
.orderBy.schoolTerm().asc().subject().asc().end()
);MyBatis Dynamic SQL Example
// Using MyBatis Dynamic SQL to build a query
mapper.selectMany(
select(
schoolTerm,
subject,
count(score).as("count"),
min(score).as("min_score"),
max(score).as("max_score"),
avg(score).as("avg_score")
).from(studentScore)
.where(schoolTerm, isGreaterThanOrEqualTo(2000))
.and(subject, isIn("英语", "数学", "语文"))
.and(score, isGreaterThanOrEqualTo(60))
.and(isDeleted, isEqualTo(false))
.groupBy(schoolTerm, subject)
.having(count(score), isGreaterThan(1)) // currently not supported
.orderBy(schoolTerm, subject)
.build(isDeleted, isEqualTo(false))
.render(RenderingStrategies.MYBATIS3)
);JOOQ Example
// Using JOOQ to build a query
dslContext.select(
STUDENT_SCORE.GENDER_MAN,
STUDENT_SCORE.SCHOOL_TERM,
STUDENT_SCORE.SUBJECT,
count(STUDENT_SCORE.SCORE).as("count"),
min(STUDENT_SCORE.SCORE).as("min_score"),
max(STUDENT_SCORE.SCORE).as("max_score"),
avg(STUDENT_SCORE.SCORE).as("avg_score")
)
.from(STUDENT_SCORE)
.where(
STUDENT_SCORE.SCHOOL_TERM.ge(2000),
STUDENT_SCORE.SUBJECT.in("英语", "数学", "语文"),
STUDENT_SCORE.SCORE.ge(60),
STUDENT_SCORE.IS_DELETED.eq(false)
)
.groupBy(STUDENT_SCORE.GENDER_MAN, STUDENT_SCORE.SCHOOL_TERM, STUDENT_SCORE.SUBJECT)
.having(count().gt(1))
.orderBy(STUDENT_SCORE.SCHOOL_TERM.asc(), STUDENT_SCORE.SUBJECT.asc())
.fetch();Fluent MyBatis Update Example
// Updating only non‑null fields with Fluent MyBatis
new StudentUpdate()
.update.name().is(student.getName(), If::notBlank)
.set.phone().is(student.getPhone(), If::notBlank)
.set.email().is(student.getEmail(), If::notBlank)
.set.gender().is(student.getGender(), If::notNull)
.end()
.where.id().eq(student.getId()).end();Generated Code Structure
Fluent MyBatis consists of two sub‑projects: Fluent Generator, which reads database metadata and generates Entity and DAO classes, and Fluent MyBatis, which provides a functional DSL for building SQL. The generated DAO extends a base DAO, while the processor module creates helper classes similar to Lombok’s annotation processing.
Workflow Overview
A typical workflow creates a Query or Update object, passes it to a Mapper, and the Mapper’s Provider methods assemble the final SQL using MyBatis’s existing execution engine, preserving features such as connection pooling and SQL injection protection.
Conclusion
Fluent MyBatis offers a modern, code‑centric alternative to XML‑heavy MyBatis configurations, delivering better readability, IDE assistance, dynamic table naming, and comprehensive SQL support, making it a compelling choice for Java backend developers.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
