You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Data MongoDB中@PrePersist与@PreUpdate替代方案咨询

解决MongoDB实体中@PrePersist/@PreUpdate失效的问题

首先得明确:@PrePersist@PreUpdateJPA规范的注解,而你用的@Document是Spring Data MongoDB的实体标识,这套体系并不支持JPA的生命周期注解,这就是它们失效的核心原因。下面给你两种可行的替代方案,完美适配MongoDB的实体生命周期管理:

方案一:使用Spring Data MongoDB的审计功能(推荐)

你已经尝试用@CreatedDate@LastModifiedDate这类注解,但因为配置错了启用开关,导致功能没生效。需要做以下调整:

1. 替换审计启用注解

把项目里的@EnableJpaAuditing换成Spring Data MongoDB专属的@EnableMongoAuditing,比如在启动类或配置类上:

@SpringBootApplication
@EnableMongoAuditing
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

2. 调整父类实体代码

去掉JPA的@EntityListeners(AuditingEntityListener.class),MongoDB审计不需要这个。同时可以用@CreatedBy@LastModifiedBy自动维护操作者信息(需要额外配置Auditor):

public class ItemDocument implements Serializable {
    private static final long serialVersionUID = 5894122627332059602L;
    @Id
    private UUID id;
    @Field("created_at")
    @CreatedDate
    private long created_at;
    @Field("created_by")
    @CreatedBy
    private String created_by;
    @Field("updated_at")
    @LastModifiedDate
    private long updated_at;
    @Field("updated_by")
    @LastModifiedBy
    private String updated_by;

    // 移除原来的@PrePersist和@PreUpdate方法,审计会自动填充时间字段
}

3. 配置Auditor(可选,用于维护created_by/updated_by)

如果需要自动设置操作者信息,实现AuditorAware接口并注册为Bean:

@Component
public class CustomAuditorAware implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        // 这里可以从SecurityContext获取当前登录用户,示例如下:
        // Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        // if (auth == null || !auth.isAuthenticated()) {
        //     return Optional.empty();
        // }
        // return Optional.of(auth.getName());
        
        // 测试阶段可以返回固定值
        return Optional.of("system-user");
    }
}

方案二:使用Spring Data MongoDB的生命周期回调注解

如果你需要更灵活的自定义逻辑(比如除了时间还要处理其他字段),可以用MongoDB专属的生命周期注解:

  • @BeforeInsert:仅在插入新文档前触发(对应JPA的@PrePersist
  • @BeforeUpdate:仅在更新文档前触发(对应JPA的@PreUpdate
  • @BeforeSave:插入和更新都会触发

修改父类代码如下:

public class ItemDocument implements Serializable {
    private static final long serialVersionUID = 5894122627332059602L;
    @Id
    private UUID id;
    @Field("created_at")
    private long created_at;
    @Field("created_by")
    private String created_by;
    @Field("updated_at")
    private long updated_at;
    @Field("updated_by")
    private String updated_by;

    @BeforeInsert
    protected void onPersist() {
        this.created_at = new Date().getTime();
        this.updated_at = this.created_at;
        this.created_by = "system"; // 手动设置创建者
    }

    @BeforeUpdate
    protected void onUpdate() {
        this.updated_at = new Date().getTime();
        this.updated_by = "system"; // 手动设置更新者
    }
}

总结

  • 如果你只是需要维护创建/更新时间和操作者,方案一的审计功能更简洁,符合Spring Data的设计理念
  • 如果需要自定义更复杂的前置逻辑,方案二的生命周期回调更灵活

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

火山引擎 最新活动