When does the JPA set a @GeneratedValue @Id

别等时光非礼了梦想. 提交于 2019-11-26 15:22:39

calling .persist() will not automatically set the id value. Your JPA provider will ensure that it is set before the entity is finally written to db. So you are right to assume that the id will be assigned when the transaction is committed. But this is not the only possible case. When you call .flush() the very same will happen.

Thomas

Update: Pay attention to Geek's comment, please. -> If GenerationType.Identity is used, the id will not be set by the provider before the entity is written to db. In this case id generation happens during the insert process on db level. Anyway, the JPA provider will ensure that the entity is updated afterwards and the generated id will be available in the @Id annotated property.

AFAIK, the ID is only guaranteed to be assigned when the persistence context is flushed. It might be assigned sooner, but it depends on the generation strategy.

The book Enterprise JavaBeans 3.1 by Rubinger and Burke says the following, on page 143 (emphasis added):

Java Persistence can also be configured to automatically generate a primary key when the persist() method is invoked through the use of the @GeneratedValue annotation atop the primary key field or setter. So, in the previous example, if we had auto key generation enabled, we could view the generated key after the persist() method completed.

The JPA Specification says (emphasis added):

A managed entity instance is an instance with a persistent identity that is currently associated with a persistence context.

And also that EntityManager.persist() makes

an instance managed and persistent

As the @Id is crucial to the identity of an entity, the only way for EntityManager.persist() to make the object managed is to establish its identity by generating the @Id.


However

Rubinger and Buke's clear statement is inconsistent with the behaviour of Hibernate. So it seems that knowledgeable people disgree about what the JPA specification intends.

According to JSR 338: JavaTM Persistence 2.1 / 3.5.3 Semantics of the Life Cycle Callback Methods for Entities,

The PostPersist and PostRemove callback methods are invoked for an entity after the entity has been made persistent or removed. These callbacks will also be invoked on all entities to which these operations are cascaded. The PostPersist and PostRemove methods will be invoked after the database insert and delete operations respectively. These database operations may occur directly after the persist, merge, or remove operations have been invoked or they may occur directly after a flush operation has occurred (which may be at the end of the transaction). Generated primary key values are available in the PostPersist method.

One possible (personally presumable) exception is GeneratorType.TABLE which the container (may) fetches values to use and (may) set it before PrePersist. I always use my id in PrePersist. I'm not sure this behaviors is specified or may not work with any other vendors.

important edit

Not all application servers set id before PrePersist. You can track JPA_SPEC.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!