小编典典

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

hibernate

@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仍包含已删除的项目。


阅读 541

收藏
2020-06-20

共1个答案

小编典典

我正在使用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)。

2020-06-20