@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_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仍包含已删除的项。
答案 0 :(得分:9)
我正在使用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] DEBUG org.hibernate.SQL - insert into Category (id, category_name) values (null, ?) Hibernate: insert into Category (id, category_name) values (null, ?) 22:54:30.824 [main] TRACE org.hibernate.type.StringType - binding null to parameter: 1 22:54:30.844 [main] DEBUG o.h.id.IdentifierGeneratorHelper - Natively generated identity: 1 ... 22:54:30.872 [main] DEBUG org.hibernate.SQL - insert into AbstractPolicyRule (id, name) values (null, ?) Hibernate: insert into AbstractPolicyRule (id, name) values (null, ?) 22:54:30.873 [main] TRACE org.hibernate.type.StringType - binding 'foo' to parameter: 1 22:54:30.874 [main] DEBUG o.h.id.IdentifierGeneratorHelper - Natively generated identity: 1 ... 22:54:30.924 [main] DEBUG org.hibernate.SQL - update AbstractPolicyRule set category_policy_id=? where id=? Hibernate: update AbstractPolicyRule set category_policy_id=? where id=? 22:54:30.927 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1 22:54:30.928 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 2 22:54:30.929 [main] DEBUG o.h.p.c.AbstractCollectionPersister - done inserting collection: 1 rows inserted 22:54:30.929 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1 ... 22:54:30.945 [main] DEBUG org.hibernate.SQL - insert into AbstractPolicyRule (id, name) values (null, ?) Hibernate: insert into AbstractPolicyRule (id, name) values (null, ?) 22:54:30.948 [main] TRACE org.hibernate.type.StringType - binding 'bar' to parameter: 1 22:54:30.948 [main] DEBUG o.h.id.IdentifierGeneratorHelper - Natively generated identity: 2 ... 22:54:30.990 [main] DEBUG org.hibernate.SQL - update AbstractPolicyRule set category_policy_id=null where category_policy_id=? and id=? Hibernate: update AbstractPolicyRule set category_policy_id=null where category_policy_id=? and id=? 22:54:30.991 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1 22:54:30.992 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 2 22:54:30.993 [main] DEBUG o.h.p.c.AbstractCollectionPersister - done deleting collection rows: 1 deleted 22:54:30.993 [main] DEBUG o.h.p.c.AbstractCollectionPersister - Inserting rows of collection: [com.stackoverflow.q3304092.Category.activePolicyRules#1] 22:54:30.994 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1 ... 22:54:30.996 [main] DEBUG org.hibernate.SQL - update AbstractPolicyRule set category_policy_id=? where id=? Hibernate: update AbstractPolicyRule set category_policy_id=? where id=? 22:54:30.997 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1 22:54:30.998 [main] TRACE org.hibernate.type.LongType - binding '2' to parameter: 2 22:54:31.002 [main] DEBUG o.h.p.c.AbstractCollectionPersister - done inserting rows: 1 inserted ... 22:54:31.015 [main] DEBUG org.hibernate.SQL - delete from AbstractPolicyRule where id=? Hibernate: delete from AbstractPolicyRule where id=? 22:54:31.017 [main] TRACE org.hibernate.type.LongType - binding '1' to parameter: 1
第一个策略规则被删除。
如果这不代表您正在做的事情,您应该提供更多代码。
更新:回复OP的评论...
哇我刚刚将saveOrUpdate调用更改为merge,现在正在适当删除。你对此有什么了解吗?
只是一个猜测:因为orphanRemoval
是JPA的事情,我想知道saveOrUpdate
是否会适当地处理它(实际上,我认为你使用的是EntityManager
API,因为你提到了JPA )。
答案 1 :(得分:4)
首先确保您的类实现hashCode()
和equals()
方法,以便hibernate知道这些项目是从集合中删除的。
然后尝试定义hibernate @Cascade
注释,指定那里的delete-orphan级联类型和观察者是否发生相同的情况。如果它以您想要的方式工作 - 报告hibernate中的错误并暂时使用专有注释。否则 - 用详细信息更新问题