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
相关产品推荐
相关产品推荐

