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

Spring Boot中@PrePersist失效导致创建时间非空约束报错

问题原因及解决方案

核心问题

你的代码中@PrePersist注解的onCreate()方法没有被触发,导致createdAt字段未初始化,违反了数据库非空约束。而@PreUpdate能正常生效,是因为更新操作针对的是已被Hibernate管理的实体,不需要代理即可触发回调;但创建新实体时,Hibernate需要生成代理类来拦截持久化前的生命周期事件,而Kotlin默认类是final的,无法被代理,所以@PrePersist回调失效。

解决方案

方案1:使用Kotlin Spring插件自动开放类

在项目的构建脚本中添加kotlin-spring插件,它会自动将带有@Entity、@Service等Spring注解的类改为open,让Hibernate可以生成代理类:

// build.gradle.kts 示例
plugins {
    id("org.springframework.boot") version "3.2.0"
    id("io.spring.dependency-management") version "1.1.4"
    kotlin("jvm") version "1.9.20"
    kotlin("plugin.spring") version "1.9.20" // 加入该插件
}

方案2:手动将实体类改为open类

直接把data class声明为open data class,允许Hibernate生成代理:

@Entity
open data class Entity(
    // ... 主构造函数中的其他字段
) {
    lateinit var createdAt: Instant
    lateinit var updatedAt: Instant

    @PrePersist
    private fun onCreate() {
        createdAt = Instant.now().also { updatedAt = it }
    }

    @PreUpdate
    private fun onUpdate() {
        updatedAt = Instant.now()
    }
}

额外优化:避免使用lateinit var(可选)

可以给时间字段设置默认值,即使回调未触发也不会出现空值,增强代码健壮性:

@Entity
open data class Entity(
    // ... 主构造函数中的其他字段
) {
    var createdAt: Instant = Instant.now()
    var updatedAt: Instant = Instant.now()

    @PrePersist
    private fun onCreate() {
        val now = Instant.now()
        createdAt = now
        updatedAt = now
    }

    @PreUpdate
    private fun onUpdate() {
        updatedAt = Instant.now()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 02:37:01