我有一个简单的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()之前
当设置@Id时,对于不同的JPA提供者,或者对于不同的生成策略,可能是不同的。但是,什么是最安全的(可移植的,符合规范的)假设,您可以提出关于生命周期中已经设置的最早点的假设?
发布于 2012-01-31 22:43:11
调用.persist()不会自动设置id值。您的JPA提供程序将确保在实体最终写入db之前设置它。因此,您正确地假设,在提交事务时将分配id。但这不是唯一可能发生的情况。当您调用.flush()时,同样的情况也会发生。
托马斯
更新:请注意极客的评论。->如果使用GenerationType.Identity,则在将实体写入数据库之前,该提供程序将不会设置id。在这种情况下,id生成发生在db级别的插入过程中。无论如何,JPA提供程序将确保实体在更新之后被更新,生成的id将在@Id注释属性中可用。
发布于 2012-01-31 22:47:40
AFAIK,只有在刷新持久性上下文时才能保证分配ID。它可能会更早地被分配,但它取决于生成策略。
发布于 2012-02-26 13:24:00
“企业”( Enterprise JavaBeans 3.1,Rubinger和Burke )一书在第143页(重点后加)写道:
Java还可以配置为在通过在主键字段或setter上使用
persist()注释调用方法时自动生成主键。因此,在前面的示例中,如果启用了自动密钥生成,则可以在persist()方法完成后查看生成的密钥。
JPA规范规定(强调后加):
托管实体实例是一个具有持久标识的实例,该实例当前与持久性上下文相关联。
也是EntityManager.persist()制造的
管理和持久的实例
由于@Id对于实体的标识至关重要,所以EntityManager.persist()使对象管理的唯一方法是通过生成@Id来建立其标识。
然而,
Rubinger和Buke的明确声明与Hibernate的行为不一致。因此,似乎知识渊博的人对JPA规范的意图有争议。
https://stackoverflow.com/questions/9087848
复制相似问题