为啥在首先合并实体时将已删除的实例传递给合并
Posted
技术标签:
【中文标题】为啥在首先合并实体时将已删除的实例传递给合并【英文标题】:Why am I getting deleted instance passed to merge, when merging the entity first为什么在首先合并实体时将已删除的实例传递给合并 【发布时间】:2014-12-10 21:38:53 【问题描述】:我相信我要删除的实体是一个托管实体。但是,无论如何,为什么要合并它然后删除它会给我以下错误:
已删除的实例传递给合并
有人在 *** 上说,如果它是托管实体,则应忽略合并。那么为什么不忽略这一点呢?
我想删除的方式是这样的:
TrialUser mergedEntity = em.merge(tu);
em.remove(mergedEntity);
但是这个错误,但如果我去掉第一行,它似乎工作正常。但我希望它是另一种方式,因为这与代码的其余部分一致。
编辑:
@PersistenceContext(unitName = "UnitName")
protected EntityManager entityManager;
@Table(name="TRIAL_USER")
@Id
private BigDecimal id;
@ManyToOne(cascade= CascadeType.ALL , fetch=FetchType.EAGER)
@JoinColumn(name="TRIAL_USER_CLASS_ID3")
private TrialUserElement trialUserElement3;
@ManyToOne(cascade= CascadeType.ALL , fetch=FetchType.EAGER)
@JoinColumn(name="TRIAL_USER_CLASS_ID1")
private TrialUserElement trialUserElement1;
@ManyToOne(cascade= CascadeType.ALL , fetch=FetchType.EAGER)
@JoinColumn(name="TRIAL_USER_CLASS_ID2")
private TrialUserElement trialUserElement2;
【问题讨论】:
您能否发布完整的 JPA 会话(从 EntityManager 开始到结束,以及 Entity 类的主要部分(即 ID 属性和任何关系)。 已编辑。我使用持久化上下文,因此不需要关闭和提交。 为了清楚起见 - 您正在使用事务范围的容器管理的持久性上下文。如果将boolean isManaged = entityManager.contains(mergedEntity);
放在合并和删除行的中间,什么值会给你?顺便提一句。为了清楚起见,最好粘贴适当且可编译的代码(您已将 trialUserElement1
加倍)并将代码 sn-p 拆分为两个类(管理用 @PersistenceContext
注释的 bean 和用 @Entity
注释的实体 bean )。
【参考方案1】:
当您在事务中运行一些代码时,当您在方法的最后提交时,您可能会遇到此错误。 在使用
注释的方法或类中使用 spring 时@Transactional
这是因为您首先删除了对象(没有提交),然后尝试更新它。
这段代码会产生异常:
@Transactional
myethod()
dao.delete(myObject);
myObject.setProperty("some value");
dao.save();
为避免错误,您不应删除然后保存在同一事务中。
【讨论】:
你可以在两者之间调用 .flush() 。例如 .delete(myObject) .flush() .save(mynewObject())【参考方案2】:JPA 规范说:
3.2.7.1 合并分离实体状态
如果 X 是一个已移除的实体实例,则会抛出 IllegalArgumentException 合并操作(否则事务提交将失败)。
这就是您无法合并已删除实体的原因。
【讨论】:
我认为反对票 [不是我顺便说一句] 可能是因为规范中引用的部分引用了与问题相反的情况。即你不能删除然后合并。但是您可以合并然后删除,这是提问者正在尝试的(实际上在许多情况下,这是删除对象/行的唯一方法)。【参考方案3】:由于我无法运行您的代码,这有点像在黑暗中拍摄,而且这些类型的问题可能会变得有点复杂。但请放心,合并然后删除应该没问题。我怀疑它可能与您的多对一关联实体有关。
在事务提交时,删除被级联到链接的实体。
即使合并对于您的父实体来说是多余的,我认为合并正在级联到已被删除的子实体,因此是例外。
尝试更改您的级联规则 - 将其拉回 CascadeType.MERGE(对于所有三个),看看您是否仍然遇到异常。或者更改为 CascadeType.DELETE,这将防止必要的合并被级联。
【讨论】:
以上是关于为啥在首先合并实体时将已删除的实例传递给合并的主要内容,如果未能解决你的问题,请参考以下文章
核心数据-后台线程中的更新实体会自动更改主线程中的 NSManagedObject 而无需合并-为啥?
将已发布的 .Net Core Web API 文件和公共 selenium/standalone-chrome 容器合并到一个 Docker 容器中
Tapestry 5.3.8 + Jetty + Hibernate 4.3.5 + XAMPP 1.8.3 - IdClass 使用(派生)实体,为啥在尝试合并时它们会分离?