JPA何时设置@GeneratedValue @Id

2022-08-31 22:36:07

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

@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 必须调用以记录生成的 ID 值。我的问题是,这种情况何时发生,说明这一点的文档在哪里。我查看了JPA规范,找不到明确的陈述。setId()

JPA规范说(着重号是后加的):

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

这是否意味着必须对对象进行管理才能使其具有重要意义?的文档说(着重号是后加的)它使“实例托管和持久化”,那么这是否意味着由该方法设置?还是直到你打电话?@IdEntityManager.persist()@IdEntityTransaction.commit()

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


答案 1

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

托马斯

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


答案 2

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


推荐