JPA何时设置@GeneratedValue @Id

Rae*_*ald 44 java jpa primary-key

我有一个简单的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
}
Run Code Online (Sandbox Code Playgroud)

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

JPA规范说(重点补充):

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

这是否试图说必须管理对象具有@Id重要意义?说明EntityManager.persist()(强调添加)的文档使"实例管理和持久",这是否意味着@Id由该方法设置?或者直到你打电话EntityTransaction.commit()

@Id设置可能是不同的JPA提供商不同,也许不同的生成策略.但是,最安全(可移植,符合规范)的假设是什么,你可以在生命周期的最早点设置它?

Tho*_*mas 21

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

托马斯

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

  • 根据 EntityManager 文档 http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#flush() flush 将“将持久性上下文同步到底层数据库”。这意味着所有池插入语句都将写入 db 以同步状态。为此,您的 JPA 提供程序需要这些 id 值。所以他们应该在调用flush后可用。不过,有些策略可能会更早地设置它们。 (2认同)

JB *_*zet 11

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


Rae*_*ald 8

Rubinger和Burke撰写的Enterprise JavaBeans 3.1一书在第143页上说明了以下内容(重点补充):

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

JPA规范说(重点补充):

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

而且也是EntityManager.persist()使

一个实例托管和持久化

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


然而

Rubinger和Buke的明确陈述与Hibernate的行为不一致.因此,知识渊博的人似乎对JPA规范的目的有何不满.