How to Build a Reusable CRUD BaseController with MyBatis‑Plus in Spring Boot
This tutorial walks through creating a generic BaseController that provides CRUD, list, pagination, and count operations for any entity by adding MyBatis‑Plus, writing a utility class for query building, configuring a pagination interceptor, and extending the base class in concrete controllers, all illustrated with complete Java code snippets.
Step 1 – Add MyBatis‑Plus Dependency
Include the Maven artifact com.baomidou:mybatis-plus-boot-starter:3.4.2 in pom.xml to bring MyBatis‑Plus into the Spring Boot project.
Step 2 – Utility Class ApprenticeUtil
This class supplies three reusable helpers: humpToLine(String str) converts camel‑case to snake_case by matching uppercase letters with a Pattern and inserting an underscore before each, then lower‑casing the result. lineToHump(String str) performs the reverse conversion by matching _(\w) and capitalising the captured character. getQueryWrapper(E entity) uses reflection to iterate over all non‑final fields of entity, builds a QueryWrapper<E>, and adds an eq condition for each non‑null field, converting the field name to snake_case via humpToLine.
Additional overloaded methods getValueForClass demonstrate how to retrieve a specific property value via JavaBeans PropertyDescriptor and Spring's ReflectionUtils, handling NoSuchFieldException and IntrospectionException.
Step 3 – Generic BaseController<S extends IService<E>, E>
The controller is annotated with Spring MVC and Swagger annotations and injects the generic service S baseService. It defines the following endpoints, each delegating to the corresponding IService method and wrapping the result with ResponseUtils.success(...): @PostMapping("/insert") –
baseService.save(entity) @PostMapping("/deleteById")–
baseService.removeByIds(ids) @PostMapping("/updateById")–
baseService.updateById(entity) @GetMapping("/getById")–
baseService.getById(id) @PostMapping("/save")–
baseService.saveOrUpdate(entity) @PostMapping("/list")– builds a QueryWrapper via ApprenticeUtil.getQueryWrapper(entity) and returns baseService.list(queryWrapper). @PostMapping("/page") – validates page (minimum 1) and size (maximum 100), constructs a Page<E>, applies optional ascending/descending order fields from PageParamDto, and returns baseService.page(page, queryWrapper). @PostMapping("/count") – uses the same QueryWrapper to call baseService.count(queryWrapper).
Step 4 – Enable Pagination
MyBatis‑Plus does not enable pagination by default. Register a PaginationInnerInterceptor for MySQL in a configuration class:
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}Step 5 – Extend BaseController in Concrete Controllers
Concrete controllers inherit from BaseController and specify the service interface and entity type. No additional CRUD code is required.
@RestController
@RequestMapping("/apprentice/dynamic")
@Api("Dynamic Management")
public class DynamicController extends BaseController<IDynamicService, Dynamic> {} @RestController
@RequestMapping("/apprentice/blog")
@Api(tags = "Blog Management")
public class BlogController extends BaseController<IBlogService, Blog> {}Project Source
Full source code is available at:
https://gitee.com/WangFuGui-Ma/mybatis-plus-pro
Java Web Project
Focused on Java backend technologies, trending internet tech, and the latest industry developments. The platform serves over 200,000 Java developers, inviting you to learn and exchange ideas together. Check the menu for Java learning resources.
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.
