# MyBatis-Plus: what the BaseMapper interface actually buys you

> MyBatis-Plus is an Apache-2.0 toolkit layered on MyBatis that supplies CRUD methods, a lambda query builder, pagination and a code generator. It suits Spring Boot teams that want to keep writing SQL but stop hand-writing single-table statements.

**baomidou/mybatis-plus** — An powerful enhanced toolkit of MyBatis for simplify development

- Repository: https://github.com/baomidou/mybatis-plus
- Website: https://baomidou.com
- Stars: 17,477 · Forks: 4,447
- Language: Java
- License: Apache-2.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/baomidou-mybatis-plus

## The boilerplate MyBatis-Plus removes

A plain MyBatis project makes you declare every statement. Even a trivial select of one row by primary key becomes an XML fragment or an annotation, and a team with thirty tables ends up maintaining a few hundred near-identical statements. MyBatis-Plus attacks that specific layer: the README says it provides "out-of-the-box interfaces for operate database", and the mechanism is inheritance. Your mapper interface extends BaseMapper, and the CRUD methods arrive without you writing them. The audience is Java teams already committed to MyBatis who do not want to switch to an ORM with a different query model. If your project has no MyBatis mappers today, the toolkit has nothing to attach to, and you would be adopting MyBatis and MyBatis-Plus at the same time.

## BaseMapper plus a lambda wrapper is the whole data flow

The README's example is short enough to read as the architecture. You declare an interface that extends BaseMapper, parameterised by your entity type, and the toolkit supplies the implementation at runtime. Queries are then expressed by building a wrapper object and calling typed method references on it. The README shows a QueryWrapper with .lambda(), .ge(User::getAge, 18), and states that MyBatis-Plus executes SELECT * FROM user WHERE age >= 18. That translation step is the core of the project: the wrapper is a Java object graph, and the toolkit renders it into SQL. Two consequences follow. The method reference gives you compile-time checking of the column name, which raw string conditions do not. And because the wrapper is built in Java, the SQL is only visible at runtime, so debugging means logging the rendered statement rather than reading a mapper file. The repository is split into modules that mirror this design: mybatis-plus-core, mybatis-plus-extension, mybatis-plus-annotation, mybatis-plus-spring, spring-boot-starter, and mybatis-plus-jsqlparser-support, with a mybatis-plus-bom for version alignment.

## Installing MyBatis-Plus and running a first query

The README gives Maven coordinates per Spring Boot generation, and the artifact name changes with it. For Spring Boot 2 the starter is mybatis-plus-boot-starter; the README's XML block for it is:

```xml
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>Latest Version</version>
</dependency>
```

Spring Boot 3 uses a different artifact, mybatis-plus-spring-boot3-starter, and Spring Boot 4 uses mybatis-plus-spring-boot4-starter. The README annotates the Spring Boot 4 starter with ^3.5.13, so an older toolkit version will not match it. Gradle users get the same coordinates, for example implementation group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: 'Latest Version'. The README writes the version as "Latest Version" rather than a number; take the current release from Maven Central instead of copying that placeholder. From v3.5.9 onward the README notes that additional artifacts may be needed. On JDK 11 or later that is mybatis-plus-jsqlparser; on JDK 8 it is mybatis-plus-jsqlparser-4.9. This matters because the SQL parsing behind wrapper rendering and pagination lives in that module.

With the dependency in place, the first real change is one line on your mapper. The README's example is an interface with an empty body:

```java
public interface UserMapper extends BaseMapper<User> {

}
```

There is no implementation to write. You then call methods the toolkit injected:

```java
List<User> userList = userMapper.selectList(
        new QueryWrapper<User>()
                .lambda()
                .ge(User::getAge, 18)
);
```

According to the README, this executes SELECT * FROM user WHERE age >= 18. If your table or column names differ from the entity field names, the mapping annotations in mybatis-plus-annotation are where you correct that, not the wrapper.

## Where the toolkit stops being the right choice

The wrapper model covers conditions on a single table well. It does not give you entity relationship management, and the README does not claim it does. Projects that expect a persistence context with dirty checking, lazy association loading and a generated join graph are looking at the wrong tool; MyBatis-Plus keeps you in SQL, which is the point, but it also means association loading is your problem. A second boundary is the parser dependency. Because wrapper rendering and pagination depend on the jsqlparser-support module from v3.5.9 onward, the JDK version you run decides which artifact you pull, and the README splits that choice explicitly between jdk11+ and jdk8. A team on an older JDK that upgrades the toolkit without adding the matching parser artifact has a broken build, not a subtle bug. Third, the generated SQL is invisible in source control. A reviewer reading a pull request sees .ge(User::getAge, 18), not the statement it produces, so the review surface for query changes is thinner than with a mapper XML file. Teams that treat SQL review as a control should weigh that.

## MyBatis-Plus against plain MyBatis and against JPA

The honest comparison is with MyBatis itself, because MyBatis-Plus is a layer on top of it and the README states it is "fully compatible with MyBatis". Plain MyBatis gives you full control of every statement and no runtime SQL generation. MyBatis-Plus adds injection of CRUD methods, the wrapper, pagination and a code generator, and in exchange you accept a runtime translation step and a dependency on the parser module. Migration in the other direction is also real: because the underlying MyBatis mapper files still work, you can keep hand-written statements for the queries that need them and use the wrapper only for the mechanical ones. That mixed mode is the practical reason teams adopt it. Against JPA the difference is the query model, not the feature list. JPA derives statements from entity mappings and a persistence context; MyBatis-Plus derives them from an explicit wrapper you construct. The first hides more and surprises you at flush time; the second shows you the condition you wrote but not the SQL. Neither is strictly safer, and the choice usually follows whether your team already thinks in SQL.

## Maintenance, releases and the Apache-2.0 terms

The repository is not archived, and the last push was on 2026-08-03. Recent releases are v3.5.17 on 2026-07-08, v3.5.16 on 2026-01-11 and v3.5.15 on 2025-11-30, with a CHANGELOG.md and changelog-temp.md at the repository root. The gap between v3.5.16 and v3.5.17 is roughly six months, and between v3.5.15 and v3.5.16 about six weeks, so release cadence is not uniform; plan upgrades against the changelog rather than a schedule. The upgrade cost concentrates in two places: the starter artifact name, which differs across Spring Boot 2, 3 and 4, and the jsqlparser-support split introduced from v3.5.9. A version bump that crosses either boundary is a build change, not just a dependency bump. On licensing, the project is under Apache-2.0, and the README points to the Apache License 2.0 text. The README also links a separate enterprise offering, Mybatis-Mate, for advanced features, and carries a line stating that illegal projects are not permitted to use it. That line is in the README, not in the licence file; if the distinction between the Apache-2.0 terms and that statement matters to your organisation, read the LICENSE file and get your own legal review rather than relying on this summary.

## Conclusion

Adopt MyBatis-Plus if your team already writes MyBatis mappers and wants single-table CRUD and pagination without generating that boilerplate by hand. Do not adopt it if you need JPA-style entity relationship management or generated joins; the toolkit does not provide them. Before committing, verify which starter matches your Spring Boot generation, whether you need the mybatis-plus-jsqlparser artifact for your JDK, and whether the code generator's output style matches the mappers your team already maintains.

## FAQ

### What is MyBatis-Plus?

It is an enhanced toolkit layered on top of MyBatis for simplifying development, under the Apache 2.0 license. The README describes it as providing out-of-the-box features such as code generation, conditional query builders and pagination plugins.

### How does MyBatis-Plus differ from plain MyBatis?

The README states MyBatis-Plus is fully compatible with MyBatis, so existing mappers keep working. The difference is the added layer: mapper interfaces extend BaseMapper to receive CRUD methods, and conditions are built through a wrapper object instead of hand-written statements.

### How do I add MyBatis-Plus to a Spring Boot project?

Add the starter for your Spring Boot generation, for example mybatis-plus-boot-starter for Spring Boot 2, mybatis-plus-spring-boot3-starter for Spring Boot 3, or mybatis-plus-spring-boot4-starter for Spring Boot 4. The README notes that from v3.5.9 you may also need mybatis-plus-jsqlparser on JDK 11 or later, or mybatis-plus-jsqlparser-4.9 on JDK 8.

### How do I write an OR condition in a MyBatis-Plus wrapper?

The README only demonstrates a single condition with QueryWrapper and .lambda(), showing .ge(User::getAge, 18) rendering to SELECT * FROM user WHERE age >= 18. It does not document the OR form, so consult the documentation site before relying on a specific method name.

### How does MyBatis-Plus compare with JPA or Hibernate?

The README does not compare them. The observable difference is the query model: MyBatis-Plus renders SQL from an explicit wrapper you construct, while JPA derives statements from entity mappings and a persistence context, so the toolkit keeps you closer to hand-written SQL.

## Sources

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

---

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