Hibernate如何修改Kotlin类中val成员的值?
Hibernate为何能修改Kotlin实体类中val修饰的id字段?
核心原因:Kotlin JPA插件的适配处理 + Hibernate的运行时修改能力
你遇到的现象是两个技术点共同作用的结果:
Kotlin JPA插件的字段修饰符调整
你使用的org.jetbrains.kotlin.plugin.jpa插件会自动对JPA实体类做适配:- 它依赖并启用了
all-open插件的功能,把@Entity注解标记的类设为open(哪怕你没显式声明),这是JPA框架对实体类的基础要求。 - 针对带
@Id+@GeneratedValue注解的val属性,插件会修改其幕后字段的修饰符:把Kotlinval默认生成的private final幕后字段,调整为非final,为Hibernate修改字段值开了口子。
- 它依赖并启用了
Hibernate的运行时字段修改机制
调用em.persist(b)时,Hibernate需要为新生成的实体分配主键ID,它会通过两种方式修改ID字段:- 反射突破限制:利用Java反射API的
AccessibleObject.setAccessible(true),绕开字段的final修饰符,直接修改字段值。 - 字节码增强:在运行时动态修改实体类的字节码,移除字段的final修饰符,或者注入修改字段的逻辑。
- 反射突破限制:利用Java反射API的
额外验证提示
你可以查看编译后的Bar类字节码:
- 编译后的id字段修饰符会是
private而非private final(JPA插件的处理结果)。 - 就算字段保留final修饰符,Hibernate的反射机制依然能强制修改其值(Java的final字段在运行时并非绝对不可修改)。
内容的提问来源于stack exchange,提问作者user2297550
相关产品推荐
相关产品推荐

