【问题标题】: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 实现,并希望坚持标准。

【问题讨论】:

    标签: java hibernate orm jpa persistence


    【解决方案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。自己还没有测试过(还)
    • 如何检查分离的实体是否已更改(不仅是新实体。)?
    猜你喜欢
    • 1970-01-01
    • 2013-06-26
    • 2013-04-12
    • 2018-03-18
    • 2013-06-03
    • 2014-08-12
    • 2017-10-21
    • 1970-01-01
    • 2011-07-16
    相关资源
    最近更新 更多