如何知道一个分离的 JPA 实体是不是已经被持久化?
Posted
技术标签:
【中文标题】如何知道一个分离的 JPA 实体是不是已经被持久化?【英文标题】:How to know if a detached JPA entity has already been persisted or not?如何知道一个分离的 JPA 实体是否已经被持久化? 【发布时间】:2011-02-16 07:34:39 【问题描述】:我的应用程序的 Web UI 层中有一个 JPA 实体实例。我想随时知道这个实体是否已经保存在数据库中,或者它是否只存在于用户会话中。
它将在业务层中,我会使用 entitymanager.contains(Entity) 方法,但在我的 UI 层中,我认为我需要一个额外的属性来指示实体是否已保存。如何实施?我目前正在考虑以下选项:
一个 JPA 属性,其默认值由数据库设置,但会在每次更新后强制重新读取? 在我的代码中手动设置或由 JPA 自动设置的非 JPA 属性?有什么建议/其他建议吗?
我正在使用 JPA 1 和 Hibernate 3.2 实现,并希望坚持标准。
【问题讨论】:
【参考方案1】:首先,让我们提醒一下实体的各种状态。来自 JPA 1.0 规范(在第 3.2 节实体实例的生命周期中):
本节介绍 用于管理的 EntityManager 操作 实体实例的生命周期。一个 实体实例可以被表征 作为新的、托管的、分离的或 删除。
新实体实例没有持久性身份,目前还没有 与持久化上下文相关联。 托管实体实例是具有持久标识的实例 当前与持久性上下文相关联。 分离的实体实例是具有持久标识的实例 不(或不再)与持久性上下文相关联。 已删除实体实例是具有持久身份的实例,与持久上下文相关联,计划从数据库中删除。
还有一个图解:
所以,根据定义,一个分离的实体已经被持久化了,我实际上不认为这是你真正的问题。现在,如果您想知道一个实体是否是新的(即没有任何持久身份),那么这个呢:
@Transient
public boolean isNew()
return (this.id == null);
【讨论】:
当然,我想知道我的实体是否是新的。我宁愿使用在数据库中设置了默认值的另一个字段,因为我没有对主键使用 JPA GeneratedValue 策略(我正在为自己设置带有 UUID 的主键,以实现跨数据库供应商/jpa 实现/集群兼容性)。 @snowflake 问题是 JPA 不支持非 pk 属性的数据库生成值,因此您必须使用 JPA 提供程序扩展(如@org.hibernate.annotations.Generated
)或在持久后刷新实体,这是丑陋的。我想知道使用@GeneratedValue
是否不是更好的选择。
感谢您的评论。没错,这很丑陋,我更喜欢使用我的 DAO 中设置的字段作为替代。
某处我读到了关于使用默认值为 null 的@Version。您可以检查是否 version != null 因为它应该在每次写入时更新。但是,我看到的例子是使用 xml。自己还没有测试过(还)
如何检查分离的实体是否已更改(不仅是新实体。)?以上是关于如何知道一个分离的 JPA 实体是不是已经被持久化?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法将分离的对象传递给 JPA 持久化? (分离的实体传递给坚持)
JPA:传递给持久化的分离实体:嵌套异常是 org.hibernate.PersistentObjectException
Spring Data JPA:一对一实例化问题:PersistentObjectException:分离实体传递给持久化