当前位置: 首页 > 面试题库 >

即使一对多关系上的orphanRemoval = true,孤儿仍保留在数据库中(JPA /休眠)

潘英豪
2023-03-14
问题内容
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "company_policies")
@DiscriminatorColumn(name = "rule_name")
public abstract class AbstractPolicyRule implements Serializable {

  @Transient
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue
  private Long id;
  private String value;

  ...
}

_

@Entity
public class Category implements Serializable {

  @Transient
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue
  private Long id;
  @Column(name = "category_name")
  private String name;

  @OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval = true)
  @JoinColumn(name = "category_policy_id", referencedColumnName = "id")
  private Set<AbstractPolicyRule> activePolicyRules;

  ...
}

更新此Set后,现有的activePolicyRules在数据库中的category_policy_id设置为null,并插入新的。我想删除原始的。

我以为添加orphanRemoval =
true可以做到这一点,但事实并非如此。我在此上看到的其他问题似乎具有双向关系,将父级设置为null可以解决该问题,但这不是双向关系。

有什么建议么?

使用Hibernate 3.5.3

编辑:仅当数据库中存在现有的AbstractPolicyRule时,才会发生这种情况,我将其从列表中删除,然后再次保存Category。它的外键category_policy_id设置为null而不是被删除。

[DEBUG] Collection found: [domain.category.Category.activePolicyRules#1], was: 
[<unreferenced>] (initialized)
[DEBUG] Flushed: 0 insertions, 2 updates, 0 deletions to 2 objects
[DEBUG] Flushed: 1 (re)creations, 0 updates, 1 removals to 1 collections
...
[DEBUG] Deleting collection: [domain.category.Category2.activePolicyRules#1]
[DEBUG] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
[DEBUG] update company_policies set category_policy_id=null where category_policy_id=?
[DEBUG] done deleting collection

由于Hibernate文档不鼓励使用以前的方法,因此还尝试了连接表:

@Entity
public class Category implements Serializable {

  @Transient
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue
  private Long id;
  @Column(name = "category_name")
  private String name;

  @OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval = true)
  @JoinTable(name = "policy_rule_mapping", 
    joinColumns = @JoinColumn(name = "category_id"), 
    inverseJoinColumns = @JoinColumn(name = "rule_id"))
  private Set<AbstractPolicyRule> activePolicyRules;

  ...
}

这有同样的问题。映射表中的行已删除,但AbstractPolicyRule仍包含已删除的项目。


问题答案:

我正在使用orphanRemoval=true单向一对多关联,没有任何问题。

实际上,我测试了您的代码和以下方案(正确AbstractPolicyRule实施equals/ hashCode):

Category category = new Category();
AbstractPolicyRule policyRule1 = new AbstractPolicyRule("foo");

category.addToActivePolicyRules(policyRule1);
em.persist(category);
em.flush();

assertNotNull(category.getId());
assertNotNull(category.getActivePolicyRules());
assertEquals(1, category.getActivePolicyRules().size());

category.removeFromActivePolicyRules(policyRule1);
category.addToActivePolicyRules(new AbstractPolicyRule("bar"));
// category = em.merge(category); // works with or without
em.flush();
assertEquals(1, category.getActivePolicyRules().size());

符合预期。在生成的跟踪下面:

22:54:30.817 [main]调试org.hibernate.SQL-插入Category(id,category_name)值(空,?)
hibernate:插入类别(id,category_name)值(null,?)
22:54:30.824 [main] TRACE org.hibernate.type.StringType-将null绑定到参数:1
22:54:30.844 [main]调试ohid.IdentifierGeneratorHelper-本地生成的身份:1
...
22:54:30.872 [main]调试org.hibernate.SQL-插入AbstractPolicyRule(id,name)值(空,?)
hibernate:插入AbstractPolicyRule(id,name)值(null,?)
22:54:30.873 [main] TRACE org.hibernate.type.StringType-将'foo'绑定到参数:1
22:54:30.874 [main]调试ohid.IdentifierGeneratorHelper-本机生成的身份:1
...
22:54:30.924 [main]调试org.hibernate.SQL-更新AbstractPolicyRule设置category_policy_id =?id =?
hibernate:更新AbstractPolicyRule设置category_policy_id =?id =?
22:54:30.927 [main] TRACE org.hibernate.type.LongType-将“ 1”绑定到参数:1
22:54:30.928 [main] TRACE org.hibernate.type.LongType-将“ 1”绑定到参数:2
22:54:30.929 [main]调试ohpcAbstractCollectionPersister-完成插入收藏:插入1行
22:54:30.929 [main]调试org.hibernate.jdbc.AbstractBatcher-执行批处理大小:1
...
22:54:30.945 [main]调试org.hibernate.SQL-插入AbstractPolicyRule(id,name)值(空,?)
hibernate:插入AbstractPolicyRule(id,name)值(null,?)
22:54:30.948 [main] TRACE org.hibernate.type.StringType-将“ bar”绑定到参数:1
22:54:30.948 [main]调试ohid.IdentifierGeneratorHelper-本机生成的身份:2
...
22:54:30.990 [main]调试org.hibernate.SQL-更新AbstractPolicyRule设置category_policy_id = null,其中category_policy_id =?和id =?
hibernate:更新AbstractPolicyRule设置category_policy_id = null,其中category_policy_id =?和id =?
22:54:30.991 [main] TRACE org.hibernate.type.LongType-将“ 1”绑定到参数:1
22:54:30.992 [main] TRACE org.hibernate.type.LongType-将“ 1”绑定到参数2
22:54:30.993 [main]调试ohpcAbstractCollectionPersister-完成删除集合行:1已删除
22:54:30.993 [main]调试ohpcAbstractCollectionPersister-插入集合行:[com.stackoverflow.q3304092.Category.activePolicyRules#1]
22:54:30.994 [main]调试org.hibernate.jdbc.AbstractBatcher-执行批处理大小:1
...
22:54:30.996 [main]调试org.hibernate.SQL-更新AbstractPolicyRule设置category_policy_id =?id =?
hibernate:更新AbstractPolicyRule设置category_policy_id =?id =?
22:54:30.997 [main] TRACE org.hibernate.type.LongType-将“ 1”绑定到参数:1
22:54:30.998 [main] TRACE org.hibernate.type.LongType-将“ 2”绑定到参数2
22:54:31.002 [main]调试ohpcAbstractCollectionPersister-完成插入行:已插入1
...
22:54:31.015 [main]调试org.hibernate.SQL-从AbstractPolicyRule删除,其中id =?
hibernate:从AbstractPolicyRule中删除,其中id =?
22:54:31.017 [main] TRACE org.hibernate.type.LongType-将“ 1”绑定到参数:1

第一条策略规则将被删除。

如果这不能代表您的工作,则可能应提供更多代码。

更新: 回答来自OP的评论…

哇,我刚刚将saveOrUpdate调用更改为merge,现在可以适当地删除它了。您对此有何见解?

只是一个猜测:既然orphanRemoval是JPA,我想知道是否saveOrUpdate可以适当地处理它(实际上,EntityManager自从您提到JPA以来,我以为您正在使用API)。



 类似资料:
  • 问题内容: 我在Hibernate参考书的第21章中有一个基本的一对多关系父母/子女。 级联仅从子级到父级(持久级联仅是因为删除子级后我不希望删除父级)。 当我向父级添加一个子级并保存该子级时,我有一个TransientObjectException … 但是在saveOrUpdate上,我有以下异常: 我真的不明白,因为拯救孩子应该通过级联来拯救父母……有什么想法吗? 更新1 该问题似乎与“ o

  • 我希望在消费者和政策这两个实体之间建立一对多关系。一个消费者应该有几个政策。 这是我想要的一个消费JSON对象的例子: 这就是我到目前为止所做的: 政策实体 消费者实体 我想没那么难,但我已经试了几个小时了,还是做不到。我刚到Spring,所以如果有人能帮助我,我会非常感激!

  • 问题内容: 也许这是一个愚蠢的问题,但这困扰了我。 我有一个从员工到车辆的双向一对多关系。当我第一次将Employee保留在数据库中时(即它没有分配的ID),我也希望保留其关联的Vehicles。 目前,这对我来说很好,除了我保存的Vehicle实体没有自动映射关联的Employee,并且在数据库中Vehicle表中的employee_id外键列为空。 我的问题是,是否可以在雇员本身被保留的同时保

  • 母实体 子实体 代码持久化 请告诉我这些步骤是否正确。我有以下例外。并且无法理解为什么父id在子表中不可用 原因:org.hibernate.exception.ConstraintViolation异常:无法将值NULL插入到列PARAM_REF_ID,表PARAM中;列不允许空值。INSERT失败。

  • 我在Django中创建了一个数据模型,它具有多对一关系(N个主题对1个用户),如下所示: 来自django。db从django导入模型。contrib。auth。模型导入用户 当我尝试在“管理”页面中加载数据模型时,出现以下错误: 我错过了数据模型中的什么吗? 谢谢。

  • 我们将设置为 1 小时,如下所示(以前设置为 72H) 使用以下Kafka命令行工具,我们将kafka 设置为< code>1H。我们的目标是清除topic - 中比1H旧的数据,因此我们使用了以下命令: 此外 两个命令都运行无误。 但问题是关于Kafka的数据,它比1H更老,仍然存在! 实际上,没有从主题分区中删除任何数据。我们有HDP Kafka集群版本1.0x和ambari 我们不明白为什么