簡體   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