Java开发 - 公共字段的自动填充
前言
如果说Java开发中有什么是让人很烦的一件事,那一定是无尽的填充字段,本篇作为观众瑰宝系列第二篇,将带来公共字段填充相关的知识点,学完此篇,让你摆脱公共字段填充带来的麻烦,节省代码,降低冗余,妥妥的给项目瘦身,还能一定程度上提高程序的运行效率,所以,你心动吗?
问题描述
可以说,几乎每张表,我们都会有create_time,update_time这样的公共字段,所以几乎每次请求时我们都要去操作这样的字段并重新赋值,这就降低了我们的开发效率,且重复的代码让人不胜其烦,所以我们想要写一个公共的方法可以统一添加这些字段,而不用处处都写相同的代码!
问题分析
我们以上一篇SpringCache的项目为基础,也可自行创建一个项目,在上一个项目中,我们在原来的数据库中添加create_time,update_time字段:
alter table user add create_time DATETIME; alter table user add update_time DATETIME;
新表字段如下:
我们清空了表中的数据, 记者修改模型数据,添加这两个新字段;
package com.codingfire.cache.entity;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class User implements Serializable {
private Long id;
private String username;
private String password;
private Integer age;
private String phone;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
接着去重新修改增删改查的代码,我们简单修改如下:
@PostMapping
@CachePut(value = "user", key = "#user.id")
// @CachePut(value = "userCache", key = "#backUser.id")
public User add(User user) {
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userService.save(user);
User backUser = user;
return backUser;
}
@PutMapping
@CachePut(value = "user", key = "#user.id")
// @CachePut(value = "userCache", key = "#backUser.id")
public User update(User user) {
user.setUpdateTime(LocalDateTime.now());
userService.updateById(user);
User backUser = user;
return backUser;
}
下面运行MySQL和Redis服务,用postman调用添加用户接口:
结果意外遇到了新问题, Redis的jackson不支持LocalDateTime时间类,这就尴尬了,但并不是无解,报错中给出了解决办法,我们按照提示做出一些调整。
添加新依赖:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.13.0</version> </dependency>
这时如果你直接运行项目,还是不行,还需要在实践属性上添加两个注解:
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
做完这些,重新启动项目,运行添加用户的API,果然运行成功,我们查看数据库:
新的数据已经添加上去了,但又没有办法隐式的添加这两个时间,而不是直接通过代码呢?我想,应该是有的,我们之前学过过滤器和拦截器,他俩的差别我就不再介绍了,感兴趣的自行查看:
Java开发 - 拦截器初体验_CodingFire的博客-CSDN博客
由此来看,这里面必定少不了他们的角色,这里我们就用过滤器吧,过滤器的拦截范围更大,一般项目都会使用,我们不妨也用一下,基调定好了,下一步我们就来看看怎么实现这个过滤器,让字段可以自动填充。
然而我们发现,写在过滤器里也不是很合适,它只能在post时通过request.getParam(key)获取数据,不能进行写操作,这就麻烦了,看来过滤器也不是很好的选择啊。
好在,天无绝人之路,我们还可以通过自定义元数据对象处理器的方式来统一添加参数,而且,可行度非常高。
解决方案
创建元数据对象处理器
package com.codingfire.cache.common;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自定义元数据对象处理器
*/
@Component
@Slf4j
public class MyMetaObjectHandle implements MetaObjectHandler {
/**
* 插入操作,自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]...");
log.info(metaObject.toString());
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime",LocalDateTime.now());
}
/**
* 更新操作,自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充[update]...");
log.info(metaObject.toString());
metaObject.setValue("updateTime",LocalDateTime.now());
}
}
删除接口内自定义添加字段
将接口中,我们手动添加的字段删掉:
@PostMapping
@CachePut(value = "user", key = "#user.id")
// @CachePut(value = "userCache", key = "#backUser.id")
public User add(User user) {
userService.save(user);
User backUser = user;
return backUser;
}
给时间字段添加注解
做完这些,还需要给自动填充的字段增加一个注解。
如果是插入填充:
@TableField(fill = FieldFill.INSERT)
如果是插入和更新时都填充:
@TableField(fill = FieldFill.INSERT_UPDATE)
测试
我们重新启动项目,用postman调用此接口,新增加一个用户:
查看数据库中新增加的用户信息是否包含了时间:
测试成功,公共字段的填充搞定。
结语
看来,解决问题时,方向一定要找对,斗则方向错了,怎么也不可能完成目标的。一开始博主想要用过滤器来完成,但是发现过滤器无法进行写操作,转而更换了方向,从元数据处理器下手,最后终于实现了公共字段填充。觉得不错,就给个赞吧。