Mybatis-Plus MetaObjectHandler實現建立人建立時間等欄位自動填充-遇到的坑
阿新 • • 發佈:2021-01-31
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.字首