Master MyBatis‑Plus in Spring Boot: From Quick Start to Advanced Features
This guide walks through integrating MyBatis‑Plus with Spring Boot, covering dependency setup, configuration, entity annotations, CRUD operations, pagination, logical deletion, enum handling, automatic field filling, multi‑data‑source support, and testing with concrete code examples and detailed explanations.
Quick Start
The article assumes a Spring Boot, Maven, JDK 1.8, and MySQL environment. It creates a database using the utf8mb4 charset to store emoji characters.
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!-- mybatis‑plus multi‑data‑source -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>Spring Boot’s main class is annotated with @MapperScan("com.wjbgn.user.mapper") to locate mapper interfaces.
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@MapperScan("com.wjbgn.user.mapper")
@SpringBootApplication
public class RobNecessitiesUserApplication {
public static void main(String[] args) {
SpringApplication.run(RobNecessitiesUserApplication.class, args);
}
}Data‑source configuration uses HikariCP (recommended over druid for performance) and defines a primary master and a slave (both pointing to the same DB in the example).
spring:
datasource:
dynamic:
primary: master
strict: false
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/rob_necessities?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
slave_1:
url: jdbc:mysql://127.0.0.1:3306/rob_necessities?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
# HikariCP tuning
spring:
datasource:
dynamic:
hikari:
max-lifetime: 1800000
connection-timeout: 5000
idle-timeout: 3600000
max-pool-size: 12
min-idle: 4
connection-test-query: /**ping*/Service Startup
Running the Spring Boot application prints a successful start‑up log, confirming that MyBatis‑Plus is correctly wired.
Usage
Entity Annotations
MyBatis‑Plus provides a set of annotations to simplify mapping. Example entity:
@TableName("user")
public class UserDO {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("nickname")
private String nickname;
private String realName;
}Key annotations explained: @TableName: specifies the table name. @TableId: defines primary‑key strategy. IdType options include AUTO (DB auto‑increment), NONE, INPUT, ASSIGN_ID (snowflake), and ASSIGN_UUID. @TableField: maps a field to a column and can set conditions such as SqlCondition.EQUAL, LIKE, etc.
CRUD
Service layer extends IService<UserDO> and implementation extends ServiceImpl<UserMapper, UserDO>:
public interface IUserService extends IService<UserDO> {}
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements IUserService {}Mapper layer simply extends BaseMapper<UserDO>:
@Mapper
public interface UserMapper extends BaseMapper<UserDO> {}Pagination
Configure the pagination interceptor:
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.wjbgn.*.mapper*")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}Logical Deletion
Global logical‑delete configuration (since 3.3.0) can be set in application.yml:
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDelete
logic-delete-value: 1
logic-not-delete-value: 0Or use the @TableLogic annotation on the entity field:
@TableLogic
private Integer isDelete;Enum Handling
Define an enum implementing IEnum<Integer> and annotate with @JsonFormat(shape = JsonFormat.Shape.OBJECT) to serialize both code and name:
public enum SexEnum implements IEnum<Integer> {
MAN(1, "男"),
WOMAN(2, "女");
private Integer code;
private String name;
SexEnum(Integer code, String name) { this.code = code; this.name = name; }
@Override
public Integer getValue() { return code; }
public String getName() { return name; }
}Entity field uses the enum directly:
@TableField(value = "sex")
private SexEnum sex;Configure package scanning for enums:
mybatis-plus:
typeEnumsPackage: com.wjbgn.*.enumsAutomatic Field Filling
Implement MetaObjectHandler to auto‑populate timestamps:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}Entity fields:
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(value = "update_time", fill = FieldFill.UPDATE)
private LocalDateTime updateTime;Multi‑DataSource
MyBatis‑Plus supports various multi‑data‑source strategies. Example YAML for master‑slave, multiple masters, or mixed DB types is provided, and the @DS annotation can be placed on classes or methods (method‑level takes precedence).
@DS("slave_1")
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements IUserService {
@DS("slave_1")
public List<UserDO> getList() { return this.list(); }
@DS("master")
public int saveUser(UserDO user) {
return this.save(user) ? 1 : 0;
}
}Testing
A sample user table is created with fields id, nickname, sex, create_time, and is_delete (logical delete flag).
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nickname` varchar(255) NOT NULL COMMENT '昵称',
`sex` tinyint(1) NOT NULL COMMENT '性别,1男2女',
`create_time` datetime NOT NULL COMMENT '创建时间',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 1是,0否',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8mb4;Controller exposes CRUD endpoints for demonstration:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@RequestMapping("/save")
public boolean save() {
UserDO user = new UserDO();
user.setNickname("大漂亮");
user.setSex(SexEnum.MAN);
return userService.save(user);
}
@RequestMapping("/update")
public boolean update(@RequestParam String nickname, @RequestParam Long id) {
UserDO user = new UserDO();
user.setId(id);
user.setNickname(nickname);
return userService.updateById(user);
}
@RequestMapping("/delete")
public boolean delete(@RequestParam Long id) {
return userService.removeById(id);
}
@RequestMapping("/list")
public List<UserDO> list() {
return userService.list();
}
@RequestMapping("/page")
public Page page(@RequestParam int current, @RequestParam int size) {
return userService.page(new Page<>(current, size), new QueryWrapper<>(new UserDO()));
}
}Running these endpoints confirms that MyBatis‑Plus integration works as expected, covering the most common features such as annotations, CRUD, pagination, logical deletion, enum conversion, automatic filling, and multi‑data‑source routing.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
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.
