概述:
我正在构建一个spring-boot应用程序,该应用程序的一部分是从外部REST服务检索一些实体,并将其与数据库中本地保存的实体的先前版本进行比较。
我注射EntityManager
用@PersistenceContext
,并用它来工作与数据库,因为有许多实体类型,类型最初是未知的模块。我可以JpaRepository
从工厂获得,但是不同实体类型的数量容易增加,如果可能的话,我宁愿不依赖它。
问题:
当模块检索它不在数据库中的实体时,它将执行一些业务逻辑,然后尝试保留新实体。
该Person
班,这是有问题的实体之一,包含类型的三个领域Site
,这往往持有相同的对象。
当我尝试使用持久保存一个在多个字段中具有Person
相同Site
对象的新对象时CascadeType.PERSIST
,我得到了一个EntityExistsException
(请参阅stacktrace(1))。
当我从Site
字段中删除CascadeType.PERSIST 并尝试在多个字段中保留Person
具有相同Site
对象的新对象时,我得到了TransientPropertyValueException
(请参见stacktrace(2))。
我想我了解两种例外情况发生的原因:
在第一种情况下,是因为在第一个站点字段被级联持久化之后,它无法在第二个字段中重新持久化。
我认为的第二种情况是因为@Transactional
注释正在尝试在不持久化站点实例的情况下刷新事务。
我尝试删除@Transactional
注释并自己开始并提交EntityTransaction,但我得到了一个IllegalStateException
(请参阅stacktrace(3)),尽管我认为这是可以预期的,因为spring应该自己处理事务本身。
我已经看过类似问题的答案(例如this,this),但都提出了更改CascadeType的一些变体。
在另一个问题中,有人建议确保该equals()
方法正确评估了有问题的实体,因此我在调试器中签入并((Person)newEntity).currentSite.equals(((Person)newEntity).homeSite)
评估为true。
如何在多个字段中一致地持久保存/合并具有相同对象的实体?
编辑:我也尝试了级联类型与的各种组合fetch = FetchType.EAGER
,但这不会改变它们各自的异常。
编辑2:我尝试使用a JpaRepository
而不是使用EntityManager
,并且根据我使用的层叠类型有效地获得了相同的异常集。
如果我使用PERSIST
,但没有MERGE
,我得到一个EntityNotFoundException
(见堆栈跟踪(4)),如果我同时使用PERSIST
和MERGE
我得到一个InvalidDataAccessApiUsageException`(见堆栈跟踪(5))。
人: …