繁体   English   中英

JPA 何时设置 @GeneratedValue @Id

[英]When does the JPA set a @GeneratedValue @Id

我有一个简单的 JPA 实体,它使用生成的long “ID”作为其主键:

@Entity
public class Player {
   private long id;

   protected Player() {
     // Do nothing; id defaults to 0L
   }


   @GeneratedValue
   @Id
   public long getId() {
      return id;
   }

   protected void setId(final long id) {
      this.id = id;
   }
   // Other code
}

在此类型对象的生命周期中的某个时刻,JPA 必须调用setId()来记录生成的 ID 值。 我的问题是,这什么时候发生,说明这一点的文档在哪里 我已经查看了 JPA 规范,但找不到明确的声明。

JPA 规范说(强调):

受管实体实例是具有当前与持久上下文相关联的持久标识的实例。

这是想说必须管理对象才能使其@Id有意义吗? EntityManager.persist()的文档说(强调)它使“实例管理和持久化”,那么这是否意味着@Id是由该方法设置的? 还是直到您调用EntityTransaction.commit()

对于不同的 JPA 提供者,以及可能对于不同的生成策略,设置@Id时间可能会有所不同。 但是,您可以对生命周期中的最早点做出的最安全(便携、符合规范)假设是什么?

调用 .persist() 不会自动设置 id 值。 您的 JPA 提供程序将确保在实体最终写入 db 之前设置它。 因此,您可以假设在提交事务时分配 id 是正确的。 但这并不是唯一可能的情况。 当你调用 .flush() 时,同样会发生。

托马斯

更新:请注意 Geek 的评论。 -> 如果使用 GenerationType.Identity,则在实体写入 db 之前提供者不会设置 id。 在这种情况下,id 生成发生在 db 级别的插入过程中。 无论如何,JPA 提供者将确保实体随后更新,并且生成的 id 将在 @Id 注释属性中可用。

AFAIK,只有在刷新持久性上下文时才保证分配 ID。 它可能会更快分配,但这取决于生成策略。

Rubinger 和 Burke所著的 Enterprise JavaBeans 3.1一书在第 143 页(添加了强调)如下:

Java Persistence 还可以配置为通过使用主键字段或 setter 顶部的@GeneratedValue注释调用persist()方法时自动生成主键。 因此,在前面的示例中,如果我们启用了自动密钥生成,则可以在persist()方法完成后查看生成的密钥。

JPA 规范说(强调):

受管实体实例是具有当前与持久上下文相关联的持久标识的实例。

还有EntityManager.persist()使得

一个实例管理和持久化

由于@Id对实体的身份至关重要,因此EntityManager.persist()管理对象的唯一方法是通过生成@Id来建立其身份。


然而

Rubinger 和 Buke 的明确声明与 Hibernate 的行为不一致。 因此,似乎知识渊博的人不同意 JPA 规范的意图。

根据JSR 338: JavaTM Persistence 2.1 / 3.5.3 Semantics of the Life Cycle Callback Methods for Entities

PostPersistPostRemove回调方法在实体被持久化或删除后被调用。 这些回调也将在这些操作级联到的所有实体上调用。 PostPersistPostRemove方法将分别在数据库插入和删除操作之后被调用。 这些数据库操作可能在调用持久、合并或删除操作之后直接发生,也可能在刷新操作发生后(可能在事务结束时)直接发生。 生成的主键值在PostPersist方法中可用

一种可能的(个人推测的)异常是GeneratorType.TABLE ,容器(可能)获取要使用的值并(可能)在PrePersist之前设置它。 我总是在PrePersist使用我的id 我不确定此行为是否已指定或可能不适用于任何其他供应商。

重要编辑

并非所有应用程序服务器都在PrePersist之前设置 id。 您可以跟踪JPA_SPEC

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM