@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单向一对多关联,没有任何问题。
orphanRemoval=true
实际上,我测试了您的代码和以下方案(正确AbstractPolicyRule实施equals/ hashCode):
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)。
orphanRemoval
saveOrUpdate
EntityManager