Master MyBatis-Plus: From Basics to Advanced Features
This article introduces MyBatis-Plus, an enhancement layer for MyBatis, and walks through its core features—non‑intrusive CRUD, Lambda queries, primary‑key strategies, automatic field filling, optimistic locking, pagination, logical delete, performance analysis, condition builders, and a code generator—providing complete code examples and configuration steps for Spring Boot integration.
MyBatis‑Plus Overview
Non‑intrusive: adds features without changing existing MyBatis code.
Low overhead: basic CRUD is auto‑injected with negligible performance impact.
Powerful CRUD: built‑in BaseMapper and service, rich QueryWrapper, Lambda support.
Automatic primary‑key generation: four strategies (ID_WORKER/Snowflake, AUTO, INPUT, UUID, ID_WORKER_STR).
ActiveRecord mode, global method injection, code generator, pagination plugin (supports MySQL, MariaDB, Oracle, DB2, H2, HSQL, SQLite, PostgreSQL, SQLServer), performance analysis plugin, logical delete interceptor.
Quick Start
Create database and table:
DROP TABLE IF EXISTS user;
CREATE TABLE user (
id BIGINT(20) NOT NULL COMMENT 'Primary Key ID',
name VARCHAR(30) NULL COMMENT 'Name',
age INT(11) NULL COMMENT 'Age',
email VARCHAR(50) NULL COMMENT 'Email',
PRIMARY KEY (id)
);Insert sample data:
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');Add Maven/Gradle dependency mybatis-plus-boot-starter to a Spring Boot project.
Configure datasource (application.yml or properties):
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&useSSL=true&useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=233031Define entity class User with fields id, name, age, email (optionally Lombok getters/setters).
Create mapper interface extending BaseMapper<User> and annotate with @Repository (or use @Mapper and enable @MapperScan).
CRUD Extensions
Insert with Automatic ID
@Test
public void testInsert() {
User user = new User();
user.setName("派大星学Java");
user.setAge(16);
user.setEmail("[email protected]");
int rows = userMapper.insert(user); // ID auto‑filled
System.out.println(rows); // affected rows
System.out.println(user); // shows generated id
}Primary‑key strategies are defined in IdType enum:
public enum IdType {
AUTO(0), // DB auto‑increment
NONE(1), // No primary key set
INPUT(2), // Manually input
ID_WORKER(3), // Default Snowflake
UUID(4), // UUID string
ID_WORKER_STR(5);
}Automatic Field Filling
Mark timestamp fields with @TableField(fill = FieldFill.INSERT) or FieldFill.INSERT_UPDATE and implement MetaObjectHandler:
@Slf4j
@Component
public class MyDateObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}Optimistic Lock
Add a version column, annotate the field with @Version, and register the interceptor:
@MapperScan("com.pdx.mapper")
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}Test case – successful update:
@Test
public void versionTest() {
User user = userMapper.selectById(1L);
user.setName("派大星");
user.setEmail("[email protected]");
userMapper.updateById(user); // succeeds
}Test case – failure when another thread updates first:
@Test
public void optimisticLockerTest() {
User user1 = userMapper.selectById(1L);
User user2 = userMapper.selectById(1L);
user1.setName("派大星111");
userMapper.updateById(user2); // increments version
userMapper.updateById(user1); // throws OptimisticLockException / returns 0
}Query Operations
@Test
public void testSelect() {
User user = userMapper.selectById(1L);
System.out.println(user);
}
List<User> batch = userMapper.selectBatchIds(Arrays.asList(1,2,3));
Map<String,Object> map = new HashMap<>();
map.put("name","派大星");
map.put("age",16);
List<User> byMap = userMapper.selectByMap(map);Pagination
Register pagination interceptor and perform a paged query:
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
Page<User> page = new Page<>(1, 5); // page 1, size 5
IPage<User> result = userMapper.selectPage(page, null);
result.getRecords().forEach(System.out::println);Logical Delete
Mark a field with @TableLogic, configure logical‑delete values, and provide LogicSqlInjector bean:
@TableLogic
private Integer deleted;
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
# application.properties
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0Calling deleteById sets deleted=1 instead of removing the row.
Performance Analysis Plugin
Register PerformanceInterceptor with a maximum execution time (e.g., 100 ms) and enable it in dev or test profile:
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor pi = new PerformanceInterceptor();
pi.setMaxTime(100); // ms
pi.setFormat(true);
return pi;
}Condition Builder
Common QueryWrapper usage examples:
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNotNull("name")
.isNotNull("email")
.ge("age", 12)
.eq("name", "派大星")
.between("age", 16, 30)
.notLike("name", "l")
.likeRight("email", "t")
.inSql("id", "select id from user where id<3")
.orderByDesc("id");
List<User> list = userMapper.selectList(wrapper);Code Generator
Configure AutoGenerator to generate entity, mapper, service, and controller code:
public class Generator {
public static void main(String[] args) {
AutoGenerator mpg = new AutoGenerator();
// Global config
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("java资讯");
gc.setOpen(false);
gc.setFileOverride(false);
gc.setServiceName("%sService");
gc.setIdType(IdType.ID_WORKER_STR);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
mpg.setGlobalConfig(gc);
// Data source
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/kuangstudy?useUnicode=true&characterEncoding=utf-8&useSSL=false");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("233031");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// Package config
PackageConfig pc = new PackageConfig();
pc.setModuleName("pdx");
pc.setParent("com");
pc.setController("controller");
pc.setEntity("pojo");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// Strategy config
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("pdx_download");
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setTablePrefix("i_");
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true);
mpg.setStrategy(strategy);
// Execute generation
mpg.execute();
}
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
IT Niuke
Focused on IT technology sharing, original and innovative content. IT Niuke, we grow together.
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.
