MyBatis-Plus简介
官方地址:https://baomidou.com/
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
而本次工作内容就是使用了它的自动填充功能,实现 Entity 对象属性值的自动填充。
自动填充功能
实现功能:在插入或更新数据时,自动插入或更新指定字段的值。例如一些特殊字段:创建时间、创建人、更新时间、更新人等。
实现原理主要分为两步:
- 实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
- @TableField 注解标记字段的填充策略。
注意事项:

关于注意事项第一点:填充原理是直接给 Entity 的属性设置值,理解起来就是,填充原理是基于 Entity 实例对象的,所以通过 Mapper SQL 语句方式、或者通过 Lambda 表达式方式都是不可行的。
关于注意事项最后一点:解释当需要通过 Mapper SQL 语句方式填充时,必须按照它的约定配置,一要求方法参数对象是 Entity 对象,二要求方法参数类型需要按照约定定义别名。
使用方法
在 Spring Boot 环境下,定义实体对象、Mapper对象、Service对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @TableName("user") @Data public class User {
@TableId(type = IdType.ASSIGN_ID) private Long id;
private String name;
private Integer age;
private String email;
@TableField(fill = FieldFill.INSERT) private Date createTime;
@TableField(fill = FieldFill.INSERT) private Long createById;
@TableField(fill = FieldFill.UPDATE) private Date updateTime; }
|
1 2 3 4
| @Mapper public interface UserMapper extends BaseMapper<User> {
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> {
@Transactional public User save(String name, Integer age, String email) { User user = new User(); user.setName(name); user.setAge(age); user.setEmail(email);
this.save(user);
return this.getById(user.getId()); }
@Transactional public User updateByLambda(Long id, Integer age) { this.lambdaUpdate() .eq(User::getId, id) .set(User::getAge, age) .update();
return this.getById(id); }
@Transactional public User updateByMethod(Long id, Integer age) { User user = new User(); user.setId(id); user.setAge(age); this.updateById(user);
return this.getById(id); }
}
|
然后,实现 MetaObjectHandler
接口,定义 MyBatis Plus 填充策略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Component public class MyMetaObjectHandler implements MetaObjectHandler {
@Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); this.strictInsertFill(metaObject, "createById", Long.class, System.currentTimeMillis()); }
@Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } }
|
最后,编写单元测试类,调用 Service 对象的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @SpringBootTest public class UserServiceTest {
@Autowired private UserServiceImpl userService;
@Test public void testSaveUser() { User user = userService.save("wray", 18, "wray20156294@gmail.com"); System.out.println(user); }
@Test public void testUpdateByLambda() { User user = userService.updateByLambda(1745704644463579138L, 19); System.out.println(user); }
@Test public void testUpdateByMethod() { User user = userService.updateByMethod(1745704644463579138L, 20); System.out.println(user); } }
|
测试发现,在调用 userService.updateByLambda
方法时,基于 Lambda 表达式修改的数据,填充策略没有生效,证实了注意事项的第一点。
完整项目示例代码:https://github.com/wangfarui/work-report/tree/main/mybatis-plus-fill
关于 @TableField 注解标记字段填充策略的疑问
自动填充功能的两步实现原理中,第二步要求指定字段标记填充策略。一开始我认为有点搞繁琐了,因为既然已经在第一步配置填充策略时指定了填充字段的名称,为何还要再标记说明一遍。
这就得先搞清楚 MyBatis-Plus 是如何实现此功能的了,假如没有第二步,现在有一个 Entity 对象需要保存,填充策略自动填充值是填充的属性值,其实并没有直接给实体对象赋值。等到后面拼接保存方法的sql语句时,判断实体对象是否存在相同字段名称的属性,然后拼接sql语句,实现字段自动填充。
上述是指实体对象确实需要自动填充,假如某个表也有相同字段,但是它不需要自动填充,如果没有第二步标记指定,就得把业务表是否填充的判断逻辑放到 MyBatis-Plus 的 MetaObjectHandler 填充方法中了,这样一个为了简化代码的自动填充功能反而变得复杂了。
因此,MyBatis-Plus 在实现自动填充功能时,不仅需要判断实体对象是否存在相同字段名称的属性,还要判断该属性是否被标记。
总结
MyBatis-Plus 的自动填充功能,在业务项目下还是很实用的,业务项目的数据表基本上都要求要有创建信息、更新信息等,这些基础数据在业务代码中会频繁出现且代码内容完全相同,使用填充功能还可以避免大量重复代码。