1. 程式人生 > 其它 >Mybatis-Plus MetaObjectHandler實現建立人建立時間等欄位自動填充-遇到的坑

Mybatis-Plus MetaObjectHandler實現建立人建立時間等欄位自動填充-遇到的坑

mybatis-plus版本3.0,springboot

1.實現MetaObjectHandler介面,重寫insertFill和updateFill方法

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    private static String CREATE_DATE = "createDate";
    private static String MODIFIED_DATE = "et.modifiedDate";
    private
static String CREATE_BY = "createBy"; private static String MODIFIED_BY = "modifiedBy"; private static String IS_DELETED = "isDeleted"; @Override public void insertFill(MetaObject metaObject) { fillValue(metaObject, CREATE_DATE, () -> getDateValue
(metaObject.getSetterType(CREATE_DATE))); try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); Map<String, String> info = AuthUtil.getInfoFromHeader(request); if (info != null) { Long userid =
MapUtils.getLong(info, "id", 0L); this.setFieldValByName(CREATE_BY, userid, metaObject); } }catch (Exception e){ log.error("e="+e.getMessage()); } this.setFieldValByName(IS_DELETED, 0, metaObject); } @Override public void updateFill(MetaObject metaObject) { fillValue(metaObject, MODIFIED_DATE, () -> getDateValue(metaObject.getSetterType(MODIFIED_DATE))); try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); Map<String, String> info = AuthUtil.getInfoFromHeader(request); if (info != null) { Long userid = MapUtils.getLong(info , "id", 0L); this.setFieldValByName(MODIFIED_BY, userid, metaObject); } }catch (Exception e){ log.error("e="+e.getMessage()); } } private void fillValue(MetaObject metaObject, String fieldName, Supplier<Object> valueSupplier) { log.debug("---------------------fieldName="+fieldName); log.debug("---------------------metaObject.hasGetter(fieldName)="+metaObject.hasGetter(fieldName)); log.debug("---------------------valueSupplier="+valueSupplier.get()); if (!metaObject.hasGetter(fieldName)) { return; } Object sidObj = metaObject.getValue(fieldName); if (sidObj == null && metaObject.hasSetter(fieldName) && valueSupplier != null) { setFieldValByName(fieldName, valueSupplier.get(), metaObject); } } private Object getDateValue(Class<?> setterType) { log.debug("---------------------setterType="+setterType); if (Date.class.equals(setterType)) { return new Date(); } else if (LocalDateTime.class.equals(setterType)) { return LocalDateTime.now(); } else if (Long.class.equals(setterType)){ return System.currentTimeMillis(); } return null; }

2.Entity表需要自動填充的欄位使用fill = FieldFill.INSERT或者fill = FieldFill.UPDATE。代表在insert或update時自動填充

@Data
@Entity
@TableName(value = "test")
public class TestEntity implements java.io.Serializable {
    /** 序列號 */

    /** 主鍵,雪花演算法產生 */

	@Id
	@JsonSerialize(using = ToStringSerializer.class)
    @ApiModelProperty(value = "主鍵,雪花演算法產生")
	@TableId
    private Long id;
   
	@TableField("name")
    private String name;

    /** 建立人 */
    @ApiModelProperty(value = "建立人")
	@TableField(value="create_by",fill = FieldFill.INSERT)
    @JsonSerialize(using = ToStringSerializer.class)
    private Long createBy;

    /** 建立時間 */
    @ApiModelProperty(value = "建立時間")
	@TableField(value="create_date",fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8",shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
	private LocalDateTime createDate;

    /** 修改者 */
    @ApiModelProperty(value = "修改者")
	@TableField(value="modified_by" ,fill = FieldFill.UPDATE)
    @JsonSerialize(using = ToStringSerializer.class)
    private Long modifiedBy;

    /** 修改時間 */
    @ApiModelProperty(value = "修改時間")
    @JsonFormat(timezone = "GMT+8",shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(value="modified_date",fill = FieldFill.UPDATE)
    private LocalDateTime modifiedDate;

    /** 是否刪除(0,否;1,是) */
    @ApiModelProperty(value = "是否刪除(0,否;1,是)")
	@TableField(value = "is_deleted",fill = FieldFill.INSERT)
    private Integer isDeleted;

}

3.在SpringBoot的Application啟動類中進行配置

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(MyApplication.class, args);
    }

    @Autowired
    private PaginationInterceptor paginationInterceptor;

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Autowired @Qualifier("dataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
		//獲取mybatis-plus全域性配置
        GlobalConfig globalConfig = GlobalConfigUtils.defaults();
		//mybatis-plus全域性配置設定元資料物件處理器為自己實現的那個
        globalConfig.setMetaObjectHandler(new MyMetaObjectHandler());
        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
		//mybatisSqlSessionFactoryBean關聯設定全域性配置
        mybatisSqlSessionFactoryBean.setGlobalConfig(globalConfig);
        Interceptor[] interceptors = {paginationInterceptor};
        mybatisSqlSessionFactoryBean.setPlugins(interceptors);
        mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        return mybatisSqlSessionFactoryBean.getObject();
    }
}

在這裡插入圖片描述
遇到的坑:
1.MyMetaObjectHandler中獲取request()為空,但是我們的當前登入人資訊又放在其中Request。後面發現報錯request 空指標異常,但是createBy的資訊又給注入成功了。。。於是加了一個try-catch,防止報錯
2.Application啟動報錯,application.yml配置檔案中不識別mybatis-plus.global-config.meta-object-handler引數,於是將MyMetaObjectHandler加在了Application中,記得globalConfig 與MybatisSqlSessionFactoryBean要繫結!!
3.注意globalConfig 要用GlobalConfig globalConfig = GlobalConfigUtils.defaults();進行獲取,不要new GlobalConfig();
4.modifiedBy注入成功,但是modifiedDate為空,也沒看到報錯,後面試了很多次,發現報錯了一個et,之前看過別人寫的遇到的坑,mybatis-plus給表設定了一個別名 et,於是給modifiedDate加上了et.字首