【问题标题】:Is it ok to reference a JPA entity that has been deleted?可以引用已删除的 JPA 实体吗?
【发布时间】:2015-08-09 01:50:04
【问题描述】:

我有一个链接到其他人的 JPA 实体 -- 像这样:

@Entity
class LinkRec implements Serializable {
    ...
   @OneToOne
   private OtherEntity otherTable;
     ...
}

所以我的逻辑最终可以删除这个实体(调用EntityManger.remove 方法),然后我想将所做的事情写入日志文件,包括 otherTable 对象的引用成员。这是 JPA 中允许的操作吗?

【问题讨论】:

    标签: jpa eclipselink jpa-2.0


    【解决方案1】:

    这是 JPA 中允许的操作吗?

    是的。

    当您调用remove 时,JPA(基础 JPA 提供程序)所做的只是“标记”该实例预计将被删除/移除。但即使事务被提交(并且实例从数据库中删除)与否,实例对象仍然保持不变。对其属性的任何更改都取决于您的操作。

    由于您将实体标记为已删除,您将无法从数据库中刷新实例的状态(调用EntityManager.refersh 方法)。你会得到一个IllegalArgumentException

    请注意,在其他情况下,如果您在登录所需内容之前refresh 实体,您可能会搞砸。

    我引用了 JPA 规范中的一段文字(参见 Synchronization to the Database 部分),它可以帮助您理解“JPA”行为

    与数据库的同步不涉及刷新任何托管实体,除非刷新操作在这些实体上显式调用或级联到它们作为 cascade=REFRESH 或 cascade=ALL 注释元素值的规范的结果

    【讨论】:

    • 一个后续:如果成员对象被延迟加载(并且尚未加载),那会是一个问题吗?这不是我的情况,但我很好奇 JPA 的工作原理。
    • 你的意思是在removeLinkRec 上调用之后?在您的情况下,您可以在提交事务之前通过otherTable 关联获取它,并且在事务提交之后取决于底层持久性上下文是否没有销毁/处置它
    【解决方案2】:

    规范中的相关行是:

    删除实体后,其状态(生成状态除外)将是调用删除操作时实体的状态。

    由于这是我在规范中可以找到的关于该主题的全部内容,我想说它可能因实施而异。在我看来,这会让你想做的事情变得危险。它可能适用于一个 JPA 实现而不适用于另一个,或者适用于一个版本而不适用于升级。

    如果我必须猜测实现,我会说@OneToOne 对象可能会正常工作。我担心的是@OneToMany之类的东西。以 Hibernate 为例:这个集合可能是水合的并且在内存中,但它也可能指向一个代理。如果它是一个代理并且你调用了 getter,它会检查数据库中的集合并且因为对象已经消失而无法加载它。

    【讨论】:

    • @Terrance 我也有类似的想法,但我想继续努力。我最简单的解决方法是在操作之前执行日志条目,如果删除操作失败,则可能会输入错误的日志条目。下一个解决方法是在操作之前编写日志条目,直到删除成功后才将其发送到日志文件,但这对于我试图避免的代码来说很笨拙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    相关资源
    最近更新 更多