【问题标题】:JPA detached entity as part of a managed entity during mergeJPA 分离实体在合并期间作为托管实体的一部分
【发布时间】:2012-05-17 17:34:17
【问题描述】:

我有一些简单的实体 bean(EJB 3.1、Glassfish、EclipseLink)的应用程序内缓存,因此我不必每次都使用 findById 在数据库中查找它们,因为应用程序需要快速。这些实体 bean 是只读的。

因此,例如实体 bean Country 或 Currency 位于本地缓存中。

Java EE 应用程序中的某个进程希望更新一个复杂的实体 bean(即客户),它使用上面的简单 bean(国家、货币...)。

然后发生的事情是,由于简单实体 bean 与 JPA 上下文的连接丢失,当在 Customer bean 上尝试 .merge() 时,JPA 希望将简单实体 bean 作为新记录保存在数据库中,虽然这些已经 100% 存在于数据库中,所以我猜这是一个“分离实体”问题。

示例。

Country country = getFromCacheByName("GB"); // detached entity, but exists in database
Customer customer = getCustomerFromJPA(); // existing JPA attached entity
customer.setCountry(country);
EntityManager.merge(customer); // pseudo code

如何修复最后一行或 bean (Customer) 本身,使其不会尝试将依赖对象 (Country) 保存在 .merge() 上?

谢谢。

【问题讨论】:

  • 就像评论一样,我在从缓存中检索它之后尝试 .merge(country) ,但它并没有真正起作用,JPA 仍然尝试将简单 bean 作为事务的一部分进行持久化(上面的最后一行代码)。无论如何,我不需要合并这些简单的 bean,我只是希望它们不要作为新记录保留在数据库中,因为它们已经存在。
  • 与原始问题无关,您是否考虑过使用Country 的外键而不是在Customer 中设置它然后合并。我想你在创建客户之前会有国家对象。
  • 嗨 Nayan,我不太明白你的建议。需要详细说明吗?
  • 类似customer.setCountryId(country.getId()),不包括整个国家对象,但它的参考完整性的主键。
  • 您好,是的,这可行。但是,如果无法完成简单的事情(我在问自己),那么所有这些 JPA 复杂性的意义何在? :)

标签: jpa ejb-3.1


【解决方案1】:

在将其设置在客户中之前,您应该在国家/地区执行 find() 或 merge()。另外,请确保它具有正确的 ID。

Merge on Customer 也应该可以工作,如果它的 Id 存在,它会尝试插入国家,这很奇怪,但这可能取决于您的配置方式。您是否在国家关系上级联合并?

请注意,EclipseLink 有自己的缓存。所以你的应用缓存可能不需要。

【讨论】:

  • 我试过做 EntityManager.merge(country) - 它没有帮助。一般关于 EclipseLink 缓存和 JPA 缓存。我在很多地方都有类似 daoSomething.findByName("a") 的代码,它返回简单的实体(即货币)。并且每次它进入数据库并执行 SELECT ... FROM currency WHERE ID = ... 就好像根本不存在缓存一样。知道如何在 EclipseLink 中激活缓存吗?我说的是完全微不足道的事情,比如通过 ID 或一列获取简单实体。
  • “你是否在国家关系上级联合并” - 关于这一点,我没有在任何关系上设置 CascadeType,所以它应该是默认的。所以客户只有一个简单的属性@ManyToOne Country country;并且没有更多注释。
  • 这是我的错。实际上,父对象上的 merge() 确实有效,我使用的代码有点复杂,而且 .merge() 根本没有被调用。感谢您的友好回答。
猜你喜欢
  • 1970-01-01
  • 2013-11-13
  • 2018-02-05
  • 2015-08-10
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
相关资源
最近更新 更多