提问人:Raedwald 提问时间:2/1/2012 最后编辑:Manuel DrieschmannsRaedwald 更新时间:11/7/2017 访问量:50589
JPA 何时设置@GeneratedValue @Id
When does the JPA set a @GeneratedValue @Id
问:
我有一个简单的 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 规范说(强调后加):
托管实体实例是具有持久性标识的实例,该标识当前与持久性上下文相关联。
这是想说必须管理对象才能具有其意义吗?
文档说(强调后加)它使“一个实例托管和持久化”,那么这是否意味着 是由该方法设置的?还是直到你打电话?@Id
EntityManager.persist()
@Id
EntityTransaction.commit()
对于不同的 JPA 提供程序,以及对于不同的生成策略,设置的时间可能会有所不同。但是,对于已设置的生命周期中的最早点,您可以做出的最安全(可移植、符合规范)的假设是什么?@Id
答:
调用 .persist() 不会自动设置 id 值。您的 JPA 提供程序将确保在实体最终写入 db 之前设置它。因此,您正确地假设在提交事务时将分配 id。但这不是唯一可能的情况。当您调用 .flush() 时,也会发生同样的情况。
托马斯
更新:请注意 Geek 的评论。-> 如果使用 GenerationType.Identity,则在将实体写入 db 之前,提供程序不会设置 id。在这种情况下,id 生成发生在 db 级别的插入过程中。无论如何,JPA 提供程序将确保实体在之后更新,并且生成的 ID 将在@Id注释属性中可用。
评论
EntityManager.flush()
@Generated
@Id
flush
strategy=GenerationType.IDENTITY
AFAIK,则仅保证在刷新持久性上下文时分配 ID。它可能会更快地分配,但这取决于生成策略。
Rubinger 和 Burke 合著的《Enterprise JavaBeans 3.1》一书在第 143 页(强调后加)中说:
Java Persistence 也可以配置为在通过使用主键字段或 setter 上的注释来调用
persist()
方法时自动生成主键。因此,在前面的示例中,如果我们启用了自动密钥生成,则可以在方法完成后查看生成的密钥。@GeneratedValue
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,
在实体持久化或删除实体后,将调用 and 回调方法。这些回调也将在级联这些操作的所有实体上调用。和 方法将分别在数据库插入和删除操作之后调用。这些数据库操作可能在调用持久性、合并或删除操作后直接发生,也可能在刷新操作发生后(可能在事务结束时)直接发生。生成的主键值在
PostPersist
方法中可用。PostPersist
PostRemove
PostPersist
PostRemove
一个可能的(个人推测的)异常是 GeneratorType.TABLE
,容器(可能)提取要使用的值,并且(可能)将其设置为 。我总是使用我的 in .我不确定是否指定了此行为,或者可能不适用于任何其他供应商。PrePersist
id
PrePersist
重要编辑
并非所有应用程序服务器都设置了 id 。您可以跟踪JPA_SPEC。PrePersist
评论