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 的自动填充功能,在业务项目下还是很实用的,业务项目的数据表基本上都要求要有创建信息、更新信息等,这些基础数据在业务代码中会频繁出现且代码内容完全相同,使用填充功能还可以避免大量重复代码。