MyBatisPlus自动化填充的坑怎么解决
更新时间:2023-12-14前言:
MyBatisPlus是一个优秀的ORM框架,它在MyBatis的基础上进行了扩展,提供了更加便捷的操作数据库的方式。其中自动填充功能是MyBatisPlus的一个重要特性,它可以在插入和更新记录时自动填充一些公共字段(如创建时间、更新时间等)。然而,在使用自动填充功能时,我们可能会遇到一些坑。接下来,我将介绍一些常见的问题和解决方案。
问题1:自动填充字段的值为空
当我们在实体类中定义了需要自动填充的字段,并配置了自动填充策略后,期望这些字段在插入和更新操作时会自动填充相应的值。然而,有时候我们会发现这些自动填充的字段的值为空,这是为什么呢?
@Configuration public class MybatisPlusConfig { @Bean public MetaObjectHandler metaObjectHandler() { return new MyMetaObjectHandler(); } } // 自定义填充策略 public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { // 自动填充逻辑 } @Override public void updateFill(MetaObject metaObject) { // 自动填充逻辑 } } // 实体类 public class User { @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; } // 测试用例 @Test public void testInsert() { User user = new User(); user.setName("张三"); userService.save(user); // ... }
以上是一个简单的示例,我们在实体类的createTime字段上配置了FieldFill.INSERT策略,在updateTime字段上配置了FieldFill.INSERT_UPDATE策略。然而,当我们执行插入操作时,发现这两个字段的值都是null。这是因为在MybatisPlus的自动填充功能中,它会根据字段的类型来判断该字段是否需要填充,默认情况下,Date类型的字段是不会自动填充的。
要解决这个问题,我们需要在自定义的MetaObjectHandler中重写getMetaObjectHandler方法,并为Date类型的字段设置填充策略:
public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } @Override public MetaObjectHandler getMetaObjectHandler(Class<?> handlerType) { return MybatisDefaultMetaObjectHandler.INSTANCE; } }
通过重写getMetaObjectHandler方法,返回MybatisDefaultMetaObjectHandler.INSTANCE实例,即可解决自动填充字段的值为空的问题。
问题2:自动填充字段的值不变
有时候我们会发现在更新记录时,自动填充字段的值并没有发生改变,原本期望它在更新操作时会更新为当前时间,但实际上其值还是插入时的值。这是为什么呢?
这个问题实际上是因为我们在更新操作时,并没有设置自动填充字段的更新值。在自定义的MetaObjectHandler中,我们需要重写updateFill方法,并为自动填充字段设置更新值:
public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void updateFill(MetaObject metaObject) { Object val = getFieldValByName("updateTime", metaObject); if (val == null) { this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); } } }
通过判断自动填充字段的值是否为空,如果为空则调用strictInsertFill方法为其设置更新值。这样就可以解决自动填充字段的值不变的问题。
问题3:自动填充字段的值覆盖
在使用自动填充功能时,我们可能会遇到一个问题,就是自动填充字段的值在插入和更新操作时会被覆盖。也就是说,如果我们在代码中手动设置了自动填充字段的值,那么在插入或更新时,自动填充字段的值会被手动设置的值覆盖掉。这是为什么呢?
这个问题是由于MyBatisPlus的自动填充功能先于SQL执行的问题导致的。当我们执行插入或更新操作时,MyBatisPlus会先执行自动填充操作,然后再执行SQL语句。而如果我们在代码中手动设置了自动填充字段的值,由于自动填充操作是先于SQL执行的,所以最终插入或更新到数据库的值仍然是自动填充的值。
要解决这个问题,我们可以通过在自定义的MetaObjectHandler中重写insertFill和updateFill方法,判断是否手动设置了自动填充字段的值,如果设置了则不进行自动填充操作:
public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { Object val = getFieldValByName("createTime", metaObject); if (val == null) { this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); } } @Override public void updateFill(MetaObject metaObject) { Object val = getFieldValByName("updateTime", metaObject); if (val == null) { this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); } } }
通过判断字段的值是否为空,如果为空则进行自动填充操作,否则不进行填充。这样就可以避免自动填充字段的值被手动设置的值覆盖的问题了。
总结:
MyBatisPlus的自动填充功能是一个很方便的特性,可以在操作数据库时减轻开发者的工作量。但在使用自动填充功能时,可能会遇到一些坑。本文介绍了几个常见的问题和解决方案,包括自动填充字段的值为空、自动填充字段的值不变以及自动填充字段的值覆盖等。通过正确地配置自定义的MetaObjectHandler,并根据需求进行相关的判断和设置,就可以解决这些问题。希望本文能帮助到大家在使用MyBatisPlus自动填充功能时更加顺利地进行开发。