【问题标题】:Is it possible to temporarily disable cascading for a Hibernate entity?是否可以暂时禁用 Hibernate 实体的级联?
【发布时间】:2015-09-15 08:52:02
【问题描述】:

给定一个 Hibernate/JPA 实体,关联实体的级联设置为 ALL

@Entity
public class Entity {
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "entity")
    private Set<RelatedEntities> relatedEntities;
}

是否可以暂时关闭级联,例如允许实体被持久化而不持久化它的相关实体?

【问题讨论】:

  • 如果您使用级联约束,您可以使用 DEFERRABLE INITIALLY IMMEDIATE 约束保持实体,而无需立即检查约束。但在交易结束时,您还必须保存相关实体。更多:stackoverflow.com/questions/5300307/…
  • 谢谢,但由于引用的文章与 SQL 关键字相关但级联由 Hibernate 管理,因此不确定这将如何工作?
  • 级联肯定由db管理(如果你不使用hibernate的create选项,你必须创建它们),我怀疑如果你添加注释,hibernate也可以验证约束,但我不使用它们。如果要保存没有相关实体的实体,可能是db结构设计不当?
  • 也许你应该使用另一个表来建立关系?
  • @MrJedi 你说的是一个完全不同的概念,根本与问题无关。

标签: java hibernate jpa cascading-deletes cascading


【解决方案1】:

不,这是不可能的,至少在我的谦虚看来,这样做也不是一件好事。当其他开发人员查看映射和确实保留/合并/删除的代码时......他们会期望应用级联并引入意外行为,如果他们监督级联在其他地方被暂时禁用的代码他们是关于改变。

但是,您可以将不具有级联字段的新实体类映射到同一个表。然后在您不希望应用级联的情况下使用该实体。

【讨论】:

  • 用例有点难以解释,但基本上一个实体被用作从 UI 操作传递数据的中介。在这种情况下,相关实体需要一个一个地重构和持久化,而不是通常的级联情况。第二个建议可能是可行的——我唯一的保留是它不可避免地会产生一些重复,但可以通过将公共部分重构为父类来减轻这种情况。
【解决方案2】:

您不能暂时禁用级联(至少据我所知),但由于您使用 Hibernate,您可以 insert new entity using HQL

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert ).executeUpdate();

总有一个“手动”解决方案,您可以在变量中记住relatedEntities 以供以后使用,并在持久化之前将null 值设置为Entity 实例上的值。

【讨论】:

  • 宁愿避免使用 HQL 解决方案,因为它不是类型安全的,并且在更改实体方面非常脆弱。如果可行,“手动”解决方案听起来更有希望 - 将 relatedEntities 设置为 null 如果它们存在则不会产生删除它们的效果吗?
  • 这是一个与您原来的问题不同的问题,因为它是关于更新现有实体而不是插入新实体。我必须检查一下,但由于RelatedEntity 是关系的拥有方,只要您不将null 设置为RelatedEntity#entity 我认为应该没问题。
  • 谢谢,最初的问题对于所有级联操作应该是相当广泛的。 (坚持只是一个例子——如果我没有说清楚,抱歉)。
  • 你是对的,第二次阅读很明显你的意思是所有级联操作,对不起。如果我第一次正确阅读,我会将答案缩短为仅“手动”建议:)
  • 不用担心,现在可以随意这样做,因为已经接受了基于“手动”建议的答案。
猜你喜欢
  • 2015-08-30
  • 2014-02-25
  • 2011-09-03
  • 2015-06-07
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多