目录
1.前言
一般公司都会有自己的数据库相关规范,里面会包含一条建表规范,约束建表时,id、created_by、created_at、updated_by、updated_at 等一些字段是必须的,阿里巴巴Java开发规范里也提到了这点。
2.抽取基类
对于这些必须字段,一般会抽取一个基类包含这些必须字段属性,其他的实体类都继承这个基类,这样就避免了很多重复的代码。
@Data
public class BaseEntity {
private Long id;
private String createdBy;
private LocalDateTime createdAt;
private String updatedBy;
private LocalDateTime updatedAt;
}
3.原生 MyBatis 的写法
当需要保存一个实体持久化到数据库表时,在原生 MyBatis 下的写法,需要主动通过 setter 和 getter 方法设置这些属性对应的值,这种写法在一些业务属性字段比较少的情况下,代码写起来简直难受自己。
例如,有一张订单幂等表,里面只有一个 order_id 的业务属性的字段,当我们需要插入数据时,代码的写法如下
@Test
void insert() {
String orderId = UUID.randomUUID().toString();
User user = UserHolder.get();
LocalDateTime now = LocalDateTime.now();
OrderIdempotent idempotent = new OrderIdempotent();
idempotent.setOrderId(orderId);
idempotent.setCreatedBy(user.getUsername());
idempotent.setUpdatedBy(user.getUsername());
idempotent.setCreatedAt(now);
idempotent.setUpdatedAt(now);
orderIdempotentMapper.insert(idempotent);
}
以上这段属性的 setter 代码,有业务价值的就 idempotent.setOrderId(orderId); 但是规范要求,又不得不手动设置更多无业务价值的字段属性。
4.MyBatis-Plus 自动填充功能
MyBatis-Plus 提供的自动填充功能,很好解决了上面问题。
首先改造基类,注解标记必填属性
@Data
public class BaseEntity {
@TableId(type = IdType.AUTO)
private Long id;
@TableField(fill = FieldFill.INSERT)
private String createdBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdAt;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updatedBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime updatedAt;
}
自定义实现类 MyMetaObjectHandler,在执行插入或更新实体的时候,自动将这些属性设置成对应的值
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject object) {
User user = UserHolder.get();
LocalDateTime now = LocalDateTime.now();
setFieldValByName("createdBy", user.getUsername(), object);
setFieldValByName("createdAt", now, object);
setFieldValByName("updatedBy", user.getUsername(), object);
setFieldValByName("updatedAt", now, object);
}
@Override
public void updateFill(MetaObject object) {
User user = UserHolder.get();
LocalDateTime now = LocalDateTime.now();
setFieldValByName("updatedBy", user.getUsername(), object);
setFieldValByName("updatedAt", now, object);
}
}