You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lombok @Builder如何添加类初始化及值变更的时间戳字段?

可行实现方案

核心问题说明

你之前的实现无法生效有两个核心原因:

  • @Temporal(TemporalType.TIMESTAMP)是JPA等ORM框架的专用注解,仅用于持久化层的时间类型映射,普通Java环境下不会触发任何自动赋值、自动更新逻辑。
  • Lombok的@Data生成的标准setter、@Builder生成的构建逻辑仅做纯字段赋值,不会内置“字段变更时更新时间戳”的附加逻辑。
    另外你当前类定义的泛型<String, String>存在语法问题:两个泛型形参重名,还会遮蔽JDK内置的java.lang.String类,如果你确实需要key、value都是String类型,直接移除泛型声明即可;如果需要通用泛型,建议改为<K, V>的标准写法。

推荐方案:手写value字段的setter,保留Lombok其他能力

这个方案不需要引入额外依赖,逻辑可控,和Lombok兼容性最好:

  1. 初始化时间createdAt设为final字段,在对象实例化时直接赋值,Builder构建、new对象时都会自动执行初始化逻辑,不需要额外处理。
  2. 编辑时间editedAt不需要加任何持久化注解,手动编写value字段的setter方法,在赋值逻辑中同步更新editedAt的值——Lombok检测到类中已存在对应字段的setter时,不会重复生成,不会产生冲突。
  3. 手写setter时保留原@NonNull的非空校验逻辑,和@Data原生生成的逻辑保持一致。

参考代码如下:

import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import java.time.Instant;

@Data
@Builder
public class SampleClass {
    @NonNull
    private String key;

    @NonNull
    private String value;

    // 实例初始化时间,final修饰不允许修改,对象创建时自动赋值
    private final Instant createdAt = Instant.now();

    // value字段修改时间
    private Instant editedAt;

    // 手动编写value的setter,拦截所有外部修改操作
    public void setValue(@NonNull String value) {
        this.value = value;
        // 每次value被修改时,同步更新编辑时间
        this.editedAt = Instant.now();
    }
}

说明:如果你的业务逻辑认为构造实例时给value赋初始值也算一次编辑,可以给editedAt字段也加上初始值Instant.now();如果认为只有构造完成后的外部修改才算编辑,保持代码中editedAt初始为null即可。


注意事项

  • 不要直接通过反射修改value字段值,这种操作会绕过setter逻辑,导致editedAt无法正常更新,常规业务开发不会出现这种情况。
  • 如果你用的是Java 8之前的版本,可以把Instant替换为java.sql.Timestamp或者java.util.Date,逻辑完全一致。
  • 如果需要对多个字段的修改做时间记录,可以给对应字段都手写setter,在setter里更新对应时间戳即可,逻辑完全通用。
  • 如果你一定要保留类的泛型定义,把类头改为public class SampleClass<K, V>即可,字段类型对应改为K、V,setter逻辑不变。

内容的提问来源于stack exchange,提问作者Ish Montalvo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 01:51:45