# MyBatis-Flex: a MyBatis enhancement layer with an APT-generated query DSL

> MyBatis-Flex sits on top of MyBatis and adds generated table classes, a QueryWrapper builder and paging without extra runtime dependencies. Here is what the repository actually shows, and where it stops short.

**mybatis-flex/mybatis-flex** — mybatis-flex is an elegant Mybatis Enhancement Framework

- Repository: https://github.com/mybatis-flex/mybatis-flex
- Website: https://mybatis-flex.com
- Stars: 2,668 · Forks: 257
- Language: Java
- License: Apache-2.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/mybatis-flex-mybatis-flex

## The gap MyBatis-Flex fills between MyBatis XML and full ORM

Plain MyBatis gives you SQL mapping and nothing else. You write the mapper interface, you write the XML or the annotations, and every condition you add at runtime means string concatenation or a separate statement. MyBatis-Flex keeps that model and adds three things on top: a BaseMapper with CRUD and paging, a QueryWrapper that builds conditions from generated column references, and a row-mapping path that lets you query without declaring an entity class at all. The README describes the framework as lightweight, depending only on MyBatis with no other third-party dependencies, which matters if you have fought dependency convergence in a large Maven build.

The intended audience is a Java team already on MyBatis that wants fewer hand-written statements for the common cases. It is not an attempt to replace JPA or to hide SQL. The generated ACCOUNT.ID.ge(100) expression still produces a WHERE clause you can read in the comment above it, and the paging example ends in LIMIT 40,10. If your team wants SQL out of sight, this is the wrong shape of tool.

## How QueryWrapper and the generated table classes fit together

The mechanism is an annotation processor. The repository carries a mybatis-flex-processor module and a mybatis-flex-annotation module, and the features list mentions JSpecify nullness annotations for API hints while noting that no checker is included. You annotate an entity with @Table, mark the key with @Id, and the processor emits a companion class whose name is the table name in upper case. That is why the README examples reference ACCOUNT and ARTICLE without ever defining them: they are generated, not written by hand.

At runtime the flow is short. A QueryWrapper collects select columns, a from target and a where tree. Each column reference carries its own comparison methods, so ACCOUNT.ID.ge(100) becomes id >= ? and ACCOUNT.USER_NAME.like("zhang") becomes user_name LIKE ?. The README shows the rendered SQL directly under each snippet, including the parameter placeholders. Paging is a method on the mapper rather than a plugin you register: mapper.paginate(5, 10, query) returns a Page<Account>, and the documented SQL ends in LIMIT 40,10 for page 5 at size 10.

The select builder also covers joins, aliases, aggregate functions and subqueries. The README shows ACCOUNT.as("a") joined to ARTICLE.as("b") with an explicit equality in the where clause, and a select list that mixes ACCOUNT.ID, ARTICLE.ID.as("articleId") and ARTICLE.TITLE. Aggregates such as max(ACCOUNT.BIRTHDAY) and avg(ACCOUNT.SEX).as("sex_avg") are accepted in the same select call. The exists() helper takes a nested QueryWrapper, which is how the not-exists style condition is expressed without raw SQL.

## Installing MyBatis-Flex and running a first query without Spring

The README's hello world path does not need Spring at all. It starts with the entity and the mapper, which is the shortest real use of the framework. Declare the entity with its table name and primary key strategy, then a mapper that extends BaseMapper and defines nothing else.

```java
@Table("tb_account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;
    private String userName;
    private Date birthday;
    private int sex;

    // getter setter
}
```

```java
public interface AccountMapper extends BaseMapper<Account> {
    // only Mapper interface define
}
```

Startup is manual when Spring is absent. MybatisFlexBootstrap takes a data source, the mapper class, and then hands back the mapper instance. The README uses HikariDataSource with a MySQL JDBC URL.

```java
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/mybatis-flex");
dataSource.setUsername("username");
dataSource.setPassword("password");

MybatisFlexBootstrap.getInstance()
        .setDataSource(dataSource)
        .addMapper(AccountMapper.class)
        .start();
```

Once started, the mapper is retrieved from the same bootstrap instance and used directly. The README's example looks up one row by primary key.

```java
AccountMapper mapper = MybatisFlexBootstrap.getInstance()
        .getMapper(AccountMapper.class);


// id = 100
Account account = mapper.selectOneById(100);
```

What you should see is the account row for id 100, or null if no row matches. If the ACCOUNT class does not resolve in your IDE, the processor did not run; that is a build configuration problem, not a runtime one. The README excerpt does not give the Maven coordinates for the core or processor artifacts, so take those from the project's own documentation rather than from this article.

## Spring Boot starters, Solon, Kotlin and the module split

The top-level layout tells you a lot about intended deployment. There are three Spring Boot starter modules (mybatis-flex-spring-boot-starter, mybatis-flex-spring-boot3-starter and mybatis-flex-spring-boot4-starter), plus mybatis-flex-solon-plugin, mybatis-flex-kotlin and mybatis-flex-loveqq-starter. The README badges list Spring Boot v2.x, v3.x and v4.x alongside Solon v2.x, and JDK 8, 11, 17, 21 and 25.

The practical consequence is that the starter is not one artifact. Picking the wrong one for your Spring Boot generation is a realistic first mistake, and the README does not spell out the mapping between starter module and Boot version in the excerpt shown here; the module names are the only signal. The Kotlin module exists as a separate artifact rather than as documentation, which suggests Kotlin users are expected to depend on it explicitly.

There is also mybatis-flex-codegen in the tree, but the README excerpt does not describe how it is invoked or what it generates. Treat code generation as something to read the docs site for rather than something you can infer from the repository layout.

## Where MyBatis-Flex is the wrong choice

The generated-class dependency is the sharpest limitation. Every QueryWrapper example in the README relies on ACCOUNT and ARTICLE existing at compile time. That means an annotation processor in your build, a rebuild whenever an entity's columns change, and friction in environments where annotation processing is restricted or where entities are produced by a different tool. If you cannot run the processor, you lose the feature that distinguishes this framework from MyBatis itself.

The second limitation is scope of documentation in the repository. The README covers QueryWrapper construction in detail and shows a paging call, but the excerpt does not document transaction handling, caching, batch inserts, or how the dialect layer is extended. The features list says multi-database support is done "through dialects flexibly", without naming the dialects or pointing at the extension interface. That is a real gap for anyone whose target database is not MySQL.

Third, the README's hello world uses a hardcoded JDBC URL, username and password in a main method. That is illustrative, not a configuration pattern to copy. There is no connection-pool or transaction guidance in the excerpt, so a reader coming from a Spring Boot starter should expect to get that from the starter rather than from these snippets.

## MyBatis-Flex against MyBatis-Plus and Fluent MyBatis

The obvious comparison is MyBatis-Plus, which occupies the same niche: a BaseMapper with CRUD, a wrapper-based condition builder and paging. The difference visible in this repository is the dependency stance and the generated-class approach. The README states MyBatis-Flex depends only on MyBatis and no other third-party dependencies, and its condition builder is built on processor-generated column constants rather than on string column names. MyBatis-Plus users migrating should expect API-level work: the wrapper classes are different, and the generated table classes have no equivalent you can reuse.

Fluent MyBatis takes a different route again, generating code from the schema so the query API is derived from the database rather than from annotated entities. That generator-first posture is heavier to set up but keeps the entity and the query surface in sync from one source. MyBatis-Flex keeps the entity as the source and derives the query constants from it.

Neither comparison is settled by the README. What the repository does show is that MyBatis-Flex is a MyBatis enhancement, not a replacement, so an existing MyBatis XML mapper can sit alongside a BaseMapper in the same project. That coexistence is the strongest argument for it over a full ORM switch.

## Release cadence, licence and upgrade cost

The last push to the repository was on 2026-09-01, and the most recent tagged release listed is v1.11.8 from 2026-07-01, preceded by v1.11.7 on 2026-05-04 and v1.11.6 on 2026-02-03. That is a patch-line cadence of roughly two to three months between releases, with the repository still receiving commits after the last tag. The project is not archived.

Upgrade cost depends on which surface you touch. The QueryWrapper API is the large one; a change to how conditions are composed would ripple through every call site. The generated classes are regenerated on each build, so they follow the processor version automatically and are not a manual migration burden. Because the framework sits on MyBatis, a MyBatis upgrade is a separate decision and the README does not state a supported MyBatis version range in the excerpt shown here.

The licence is Apache-2.0, per the LICENSE file at the repository root and the badge in the README. That permits commercial use and modification with the usual notice and attribution conditions. This is not legal advice; if you redistribute the framework or embed it in a product, have your own counsel read the licence text rather than relying on a summary.

## Conclusion

Adopt MyBatis-Flex if you already run MyBatis on JDK 8 through 25 and want typed query conditions, generated table classes and paging without adding a runtime dependency beyond MyBatis itself. Skip it if your project is committed to MyBatis-Plus APIs, or if you cannot tolerate an annotation processor in the compile step, since the generated ACCOUNT and ARTICLE classes are what make the QueryWrapper examples compile. Before committing, verify three things in your own build: that the mybatis-flex-processor artifact is wired into annotation processing, that the starter version matches your Spring Boot generation (2.x, 3.x and 4.x starters are separate modules), and that your dialect is among those the core supports, because the README documents MySQL JDBC URLs and multi-database support through dialects but does not list every dialect in the excerpt shown here.

## FAQ

### What is MyBatis used for?

MyBatis is the SQL mapping framework MyBatis-Flex enhances. MyBatis-Flex builds on it by adding a BaseMapper with CRUD and paging, a QueryWrapper for conditions, and row mapping that works without entity classes, while depending only on MyBatis.

### What is the difference between iBatis and MyBatis?

The repository does not discuss the iBatis rename or its history. What it does state is that MyBatis-Flex is a MyBatis enhancement framework that depends only on MyBatis and adds generated table classes, QueryWrapper conditions and paging on top of it.

### What are the key differences between JPA and MyBatis?

The README does not compare MyBatis-Flex with JPA. It positions the framework as a MyBatis enhancement rather than a replacement, and the QueryWrapper examples still show the SQL that will run, including the LIMIT clause on paged queries.

### How can I use MyBatis with Spring Boot?

MyBatis-Flex ships separate Spring Boot starter modules for v2.x, v3.x and v4.x, and the README badges list all three. The README excerpt does not document the configuration properties for those starters, so the module names are the only signal about which one to pick.

## Sources

- [License: Apache-2.0](https://github.com/mybatis-flex/mybatis-flex/blob/main/LICENSE)
- [mybatis-flex/mybatis-flex on GitHub](https://github.com/mybatis-flex/mybatis-flex)
- [Project website](https://mybatis-flex.com)
- [README](https://github.com/mybatis-flex/mybatis-flex/blob/main/README.md)
- [Releases](https://github.com/mybatis-flex/mybatis-flex/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mybatis-flex-mybatis-flex
