前言
MybatisPlus是一个 MyBatis的增强工具,集成了mybatis和hibernate各自的优点,所以很受一些企业的喜爱。目前我们公司就在使用,确实特别好用。本文重点介绍自动填充公共字段及特定字段类型设置默认值的方法。
之前写过一篇关于JPA和mybatis自动填充的文章,有兴趣的小伙伴可以进行查看:链接
属性填充
首先MP为我们提供了元数据处理接口MetaObjectHandler,里面提供了很多默认填充实现方法供我们使用。其中insertFill和updateFill是新建和更新的填充方法,默认没有实现,需要我们自己实现。
其实现原理和mybatis的一样,在MybatisPlusAutoConfiguration自动配置类里面会根据MetaObjectHandler.class找到相应的Bean,然后配置到全局配置的元对象字段填充控制器属性上。源码如下:
获取Bean并设置
自定义属性填充器
直接上代码,注意点如下:
- 需要将填充器注入到spring容器,此处直接加@Component。
- 填充的fieldName是实体类的属性名,而不是对应表的字段名。
/**3. 元对象字段填充控制器4. 自定义填充公共字段 ,即没有传的字段自动填充5. 6. @author gourd.hu**/
@Component
public class FillMetaObjectHandler implements MetaObjectHandler {/*** 新增填充** @param metaObject*/@Overridepublic void insertFill(MetaObject metaObject) {JwtToken currentUser = JwtUtil.getCurrentUser();// 创建填充fillCreateMeta(metaObject, currentUser);// 更新填充fillUpdateMeta(metaObject, currentUser);}/*** 更新填充** @param metaObject*/@Overridepublic void updateFill(MetaObject metaObject) {JwtToken currentUser = JwtUtil.getCurrentUser();fillUpdateMeta(metaObject,currentUser);}/*** 填充创建数据* @param metaObject* @param currentUser*/private void fillCreateMeta(MetaObject metaObject, JwtToken currentUser) {Long userId = currentUser == null ? 1L: currentUser.getUserId();String userName = currentUser == null ? "007": currentUser.getUserName();if (metaObject.hasGetter(RbacConstant.META_CREATED_BY) && metaObject.hasGetter(RbacConstant.META_CREATED_TIME)) {this.strictInsertFill(metaObject,RbacConstant.META_CREATED_BY,Long.class, userId);this.strictInsertFill(metaObject,RbacConstant.META_CREATED_TIME,LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject,RbacConstant.META_DELETED,Boolean.class,Boolean.FALSE);this.strictInsertFill(metaObject,RbacConstant.META_VERSION,Integer.class,1);}if(metaObject.hasGetter(RbacConstant.META_CREATED_NAME)){this.strictInsertFill(metaObject,RbacConstant.META_CREATED_NAME,String.class, userName);}}/*** 填充更新数据* @param metaObject* @param currentUser*/private void fillUpdateMeta(MetaObject metaObject, JwtToken currentUser) {Long userId = currentUser == null ? 1L: currentUser.getUserId();String userName = currentUser == null ? "007": currentUser.getUserName();if (metaObject.hasGetter(RbacConstant.META_UPDATED_BY) && metaObject.hasGetter(RbacConstant.META_UPDATED_TIME)) {// fillStrategy方法会判断属性是否有值,如果有值就不会覆盖,所以调整为setFieldValByName方法this.strictUpdateFill(metaObject,RbacConstant.META_UPDATED_BY,Long.class, userId);this.strictUpdateFill(metaObject,RbacConstant.META_UPDATED_TIME,LocalDateTime.class, LocalDateTime.now());}if(metaObject.hasGetter(RbacConstant.META_UPDATED_NAME)){this.strictUpdateFill(metaObject,RbacConstant.META_UPDATED_NAME,String.class, userName);}}
}
这样就可以实现属性的自动填充了。当然里面的填充逻辑,可以根据自己业务自定义调整。
特定类型属性设置默认值
有些时候,我们需要数据的一些字段不存储null值,我们可以通过给这些字段填充默认值实现。有三种方式:
- 数据库字段直接设置默认值,但如果代码中自定义sql插入还是可以填充null值。
- 实体属性设置默认值,如 private Integer count=0;但是这种情况在更新的时候,会存在误更新。
- 自定义填充器,创建填充时为特定类型设置默认值。
如下:
/*** 填充创建数据* @param metaObject* @param currentUser*/private void fillCreateMeta(MetaObject metaObject, JwtToken currentUser) {Long userId = currentUser == null ? 1L: currentUser.getUserId();String userName = currentUser == null ? "007": currentUser.getUserName();if (metaObject.hasGetter(RbacConstant.META_CREATED_BY) && metaObject.hasGetter(RbacConstant.META_CREATED_TIME)) {this.strictInsertFill(metaObject,RbacConstant.META_CREATED_BY,Long.class, userId);this.strictInsertFill(metaObject,RbacConstant.META_CREATED_TIME,LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject,RbacConstant.META_DELETED,Boolean.class,Boolean.FALSE);this.strictInsertFill(metaObject,RbacConstant.META_VERSION,Integer.class,1);}if(metaObject.hasGetter(RbacConstant.META_CREATED_NAME)){this.strictInsertFill(metaObject,RbacConstant.META_CREATED_NAME,String.class, userName);}// 插入数据,Integer默认设置0,String类型默认设置空字符串List<TableFieldInfo> fieldList = this.findTableInfo(metaObject).getFieldList();Object originalObject = metaObject.getOriginalObject();for (TableFieldInfo fieldInfo : fieldList) {if(Integer.class.equals(fieldInfo.getPropertyType())){try {Object o = fieldInfo.getField().get(originalObject);if(o == null){this.strictInsertFill(metaObject,fieldInfo.getProperty(), Integer.class,0);}} catch (IllegalAccessException e) {log.error("Integer类型属性值填充异常");}}if(String.class.equals(fieldInfo.getPropertyType())){try {Object o = fieldInfo.getField().get(originalObject);if(o == null){this.strictInsertFill(metaObject,fieldInfo.getProperty(), String.class,"");}} catch (IllegalAccessException e) {log.error("String类型属性值填充异常");}}}}
这样就实现了特定类型属性设置默认值,如果你有更好的方式,欢迎评论告知。