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

Spring Data JDBC中@CreatedDate更新时被设为null的问题

问题解决:Spring Data JDBC @CreatedDate更新时被设为null

这是Spring Data JDBC的预期行为,它的审计逻辑和JPA不同:@CreatedDate仅在实体首次插入时自动赋值,更新操作时不会自动保留原有字段值,也不会跳过该字段的更新——如果实体中的createdAt为null,就会把null写入数据库。

可行解决方案(除你提到的两种外)

1. 使用@ReadOnlyProperty注解

Spring Data JDBC提供的@ReadOnlyProperty可以标记字段为只读,更新时会忽略该字段,不会将null值写入数据库。只需在createdAt字段上添加该注解:

@Table("my_entity")
public class MyEntity {

    @Id
    private final Long id;

    @Column("created_at")
    @CreatedDate
    @ReadOnlyProperty // 新增只读标记
    private Instant createdAt;

    public MyEntity (Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public Instant getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Instant createdAt) {
        this.createdAt = createdAt;
    }
}

2. 自定义更新回调

通过实现BeforeConvertCallback,在更新前自动填充原有createdAt值,适合需要更灵活审计逻辑的场景:

@Component
public class MyEntityAuditCallback implements BeforeConvertCallback<MyEntity> {

    private final MyRepository repository;

    public MyEntityAuditCallback(MyRepository repository) {
        this.repository = repository;
    }

    @Override
    public MyEntity onBeforeConvert(MyEntity entity) {
        // 若实体已有ID(更新操作),从数据库获取原有createdAt值
        if (entity.getId() != null) {
            repository.findById(entity.getId())
                .ifPresent(existingEntity -> entity.setCreatedAt(existingEntity.getCreatedAt()));
        }
        return entity;
    }
}

为什么之前的尝试无效

  • 移除getter/setter:Spring Data JDBC需要访问字段进行读写操作,且审计逻辑与getter/setter无直接关联,因此该操作无效。
  • JPA的updatable=false:Spring Data JDBC的@Column注解不支持该属性,它的字段更新控制逻辑与JPA完全独立,因此此方案不适用。

关于配置

你的@EnableJdbcAuditing配置是正确的,它已经开启了JDBC审计功能,但该功能默认仅在插入时处理@CreatedDate,更新时不会自动维护该字段,因此需要通过上述方案补充控制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 09:24:26