2010-07-21 13 views
12
@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; 

    ... 
} 

जब यह सेट अद्यतन किया जाता है मौजूदा activePolicyRules उनके category_policy_id में शून्य पर निर्धारित किया है पर = सच भी orphanRemoval साथ डेटाबेस में रहने डेटाबेस और नए डाले गए हैं। मैं मूल लोगों को हटाना चाहता हूं।

मैं orphanRemoval = सच कहा कि क्या करना होगा सोचा लेकिन यह नहीं है। इस पर मैंने जिन अन्य प्रश्नों को देखा है, वे द्वि-दिशात्मक रिश्ते हैं और माता-पिता को शून्य हल करने के लिए सेट करते हैं, लेकिन यह द्वि-दिशात्मक संबंध नहीं है।

कोई सुझाव?

हाइबरनेट 3.5.3 का उपयोग

संपादित करें: यह केवल तब होता एक मौजूदा AbstractPolicyRule डेटाबेस में मौजूद है जब, मैं इसे सूची से हटाने और फिर श्रेणी फिर से सहेजें। यह विदेशी कुंजी है, category_policy_id, हटाए जाने की बजाय शून्य पर सेट है।

[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 

इसके अलावा एक मेज में शामिल होने की कोशिश की क्योंकि हाइबरनेट प्रलेखन पिछले रास्ता हतोत्साहित:

@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; 

    ... 
} 

यह वही समस्या है। मानचित्रण तालिका में पंक्ति हटा दी गई है लेकिन सार नीति नीति में अभी भी हटाई गई वस्तु है।

+0

मैंने जो परिदृश्य परीक्षण किया वह वास्तव में आपके संपादन के बहुत करीब था। मैंने संग्रह से मौजूदा तत्व को किसी अन्य को जोड़ने के बिना अपना परीक्षण बदल दिया और यह अभी भी हटा दिया गया है। ध्यान दें कि मैं किसी विरासत का उपयोग नहीं कर रहा हूं (मुझे लगता है कि आप हो सकते हैं)। –

उत्तर

9

मैं बिना किसी समस्या के एक यूनिडायरेक्शनल एक-से-कई संघ के साथ orphanRemoval=true उपयोग कर रहा हूँ के साथ सवाल अद्यतन करें।

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()); 

बस के रूप में उम्मीद काम करता है:

और वास्तव में, मैं अपने कोड और इस परिदृश्य (AbstractPolicyRule को लागू करने equals/hashCode सही ढंग से) का परीक्षण किया। उत्पन्न निशान से नीचे:

 
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 

पहले नीति नियम हट जाता है।

यदि यह आप क्या कर रहे हैं के प्रतिनिधि नहीं है, तो आप शायद अधिक कोड प्रदान करना चाहिए।

अद्यतन: ओपी से एक टिप्पणी का जवाब ...

वाह मैं सिर्फ मर्ज करने के लिए saveOrUpdate कॉल बदल गया है और अब यह उचित रूप से हटाने के है। आपके पास कोई अंतर्दृष्टि है क्यों वह है?

बस एक अनुमान: के बाद से orphanRemoval एक जेपीए बात है, मुझे आश्चर्य है अगर saveOrUpdate यह (वास्तव में, मैंने सोचा कि आप EntityManager एपीआई का उपयोग कर रहे थे जब से तुम जेपीए उल्लेख किया) के साथ उचित रूप से सौदा होगा।

+0

उत्तर के लिए धन्यवाद। मैंने अपनी पोस्ट को अधिक जानकारी के साथ अपडेट किया है जो उम्मीदपूर्वक समझ में आता है। – Josh

+0

शायद मैं समझ नहीं पा रहा हूं कि "सेट बराबर/हैश कोड सही तरीके से" क्या है। अभी बराबर/हैश कोड तालिका के लिए अद्वितीय पहचानकर्ताओं का उपयोग कर रहा है (लेकिन आईडी नहीं)। – Josh

+0

@ जोश यह एक अच्छा कार्यान्वयन है (और मैंने समस्या को पुन: पेश करने का प्रयास करते समय उपर्युक्त कार्यान्वयन का उपयोग किया)। –

3

पहले सुनिश्चित करें कि अपनी कक्षाओं, hashCode() और equals() तरीकों लागू करते हैं ताकि हाइबरनेट जानता है कि वास्तव में इन मदों सेट से निकाल दिए जाते हैं।

फिर हाइबरनेट @Cascade एनोटेशन को परिभाषित करने का प्रयास करें, हटाएं-अनाथ कैस्केड प्रकार निर्दिष्ट करें और पर्यवेक्षक को ऐसा ही होता है या नहीं। यदि यह आपके इच्छित तरीके से काम करता है - हाइबरनेट में एक बग की रिपोर्ट करें और अस्थायी रूप से मालिकाना एनोटेशन का उपयोग करें। अन्यथा - विवरण

+0

उत्तर के लिए धन्यवाद। मैंने अपनी पोस्ट को और जानकारी के साथ अपडेट किया है। – Josh

संबंधित मुद्दे