How MybatisPlus Pro Supercharges CRUD Development Efficiency

The article explains how MybatisPlus Pro extends MybatisPlus to eliminate repetitive Service and Controller code, provides a ready‑to‑use BaseController, automatic QueryWrapper generation, and deepens the understanding of its dynamic proxy, interceptor chain and SQL injection mechanisms, while also outlining its strengths, limitations, suitable scenarios and common pitfalls.

macrozheng
macrozheng
macrozheng
How MybatisPlus Pro Supercharges CRUD Development Efficiency

Why MybatisPlus Pro Is Needed

Typical single‑table CRUD with MyBatis requires writing XML mappers and repetitive Service/Controller code, leading to high code duplication and low development efficiency. The author lists four pain points: redundant Service methods, repetitive Controllers, inconsistent code quality, and duplicated condition‑query logic.

What MybatisPlus Pro Is

MybatisPlus Pro builds on MybatisPlus, adding a set of ready‑made templates and a BaseController that eliminates Service and Controller boilerplate, allowing developers to focus on business logic.

Two interpretations exist: a community‑driven extension (the version demonstrated) and the official Pro‑level features. This article focuses on the former.

Quick Start

Step 1 – Add Dependency

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.5.15</version>
</dependency>
Version 3.5.15 (released 2025‑11‑30) supports SpringBoot 4.0.0 and Jackson 3.0.

Step 2 – Utility Class

The utility provides three core functions:

Camel‑case ↔ snake‑case conversion for automatic field‑column mapping.

Reflection‑based extraction of entity field values.

Automatic generation of QueryWrapper<E> from non‑null fields.

public class ApprenticeUtil {
    private static Pattern humpPattern = Pattern.compile("[A-Z]");
    private static Pattern linePattern = Pattern.compile("_(\\w)");
    // camel → snake
    public static String humpToLine(String str) { ... }
    // snake → camel
    public static String lineToHump(String str) { ... }
    // generate QueryWrapper from entity
    public static <E> QueryWrapper<E> getQueryWrapper(E entity) { ... }
}

The method iterates over declared fields, skips final fields, makes them accessible, reads non‑null values, converts the field name to snake case, and adds an eq condition to the wrapper.

Step 3 – BaseController

public class BaseController<S extends IService<T>, T> {
    @Autowired
    protected S baseService;
    @PostMapping("add")
    public Result add(@RequestBody T entity) { return Result.success(baseService.save(entity)); }
    @PostMapping("update")
    public Result update(@RequestBody T entity) { return Result.success(baseService.updateById(entity)); }
    @GetMapping("delete")
    public Result delete(String id) { return Result.success(baseService.removeById(id)); }
    @GetMapping("detail")
    public Result detail(String id) { return Result.success(baseService.getById(id)); }
    @PostMapping("list")
    public Result list(@RequestBody T entity) {
        QueryWrapper<T> wrapper = ApprenticeUtil.getQueryWrapper(entity);
        if (wrapper == null) wrapper = new QueryWrapper<>();
        return Result.success(baseService.list(wrapper));
    }
    @PostMapping("page")
    public Result page(@RequestBody PageDto<T> pageDto) {
        T entity = pageDto.getEntity();
        QueryWrapper<T> wrapper = ApprenticeUtil.getQueryWrapper(entity);
        if (wrapper == null) wrapper = new QueryWrapper<>();
        IPage<T> page = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        return Result.success(baseService.page(page, wrapper));
    }
}

All CRUD, pagination and list endpoints are provided without writing a single line of SQL.

Step 4 – Real‑World Usage

@Data
@TableName("product")
public class Product {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private BigDecimal price;
    private Integer stock;
    private LocalDateTime createTime;
}

public interface ProductService extends IService<Product> {}

@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {}

@RestController
@RequestMapping("/product")
public class ProductController extends BaseController<ProductService, Product> {}

Only the class declaration is needed; the entire CRUD API is ready.

Deep Dive into the Underlying Mechanism

The author explains how MybatisPlus Pro knows which table to operate on and how SQL is generated.

SQL Execution Chain

A flow diagram (image below) shows the path from Controller to database.

BaseMapper Injection Mechanism

MyBatis reads mybatis-config.xml to build a SqlSessionFactory. MybatisPlus adds a SqlInjector that generates MappedStatement objects for all BaseMapper methods during startup, and registers them in MyBatis’ configuration, eliminating the need for XML.

Four key techniques are highlighted:

Dynamic Proxy: Spring creates JDK proxies for all interfaces extending BaseMapper. Calls like productMapper.selectById(1L) are intercepted by MapperProxy, which determines the intended operation.

MappedStatement Auto‑Generation: The injector creates the SQL template, parameter and result metadata for each generic method.

Interceptor Chain: MybatisPlusInterceptor injects pagination, optimistic lock, multi‑tenant and other enhancements before the executor runs.

Method Resolution: The framework distinguishes between generic and custom methods and fetches the appropriate MappedStatement.

Wrapper Working Principle

When building a condition query, the wrapper converts method references (e.g., User::getName) into type‑safe column references, avoiding hard‑coded strings and compile‑time errors.

Pros and Cons

Advantages

Exponential boost in development speed – a module can be functional with only a BaseController inheritance, reducing code by >80%.

Uniform code style simplifies onboarding and maintenance.

Zero XML configuration for CRUD; Pro further removes Controller boilerplate.

Feature‑complete out‑of‑the‑box: built‑in pagination, rich condition builder (eq, like, between, orderBy).

Non‑intrusive – raw MyBatis can still be used for complex queries.

Disadvantages

Complex multi‑table joins become cumbersome with the Wrapper API.

Default select * can cause performance issues; developers must explicitly select needed columns.

String‑based wrappers hide column‑name changes; LambdaWrapper is recommended.

Over‑encapsulation may limit fine‑grained control in performance‑critical paths.

Usage Scenarios & Selection Guidance

Recommended for small‑to‑medium projects, rapid‑iteration back‑office systems, and any application where CRUD dominates (>80% of operations). Not advised for high‑throughput transaction systems, complex reporting, or security‑sensitive environments that require hand‑crafted SQL auditability.

Pitfall Guide

Avoid overusing generic selectList with SELECT *; specify fields for high‑frequency queries.

Prefer LambdaQueryWrapper over string‑based QueryWrapper for type safety.

Always use MybatisPlus’s pagination plugin instead of manual LIMIT.

For three‑table or more joins, write native SQL in XML rather than forcing the Wrapper.

Follow camel‑case naming for entity fields to keep automatic mapping reliable.

Conclusion

MybatisPlus Pro’s core goal is to free developers from repetitive code, delivering a “zero‑code” experience for most CRUD scenarios while preserving MyBatis’s flexibility for complex cases. It dramatically improves productivity for the majority of simple data‑driven modules, though it is not a silver bullet for all performance‑critical or multi‑join use cases.

MybatisPlus official documentation: https://baomidou.com MybatisPlusPro project repository: https://gitee.com/nirui-gitee/mybatis-plus-pro
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaCode GenerationSpring BootORMCRUDMybatisPlus
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.