2009-09-11 17 views
17

मैं अपने मॉडल में एक संग्रह है कि मेरे रूट डोमेन वस्तु की 'पिछले संस्करणों' का एक सेट होता है लोड किए बिना एक संग्रह में एक नया आइटम जारी रहती है कैसे। पिछले संस्करण इसलिए 'अपरिवर्तनीय' हैं और हम उन्हें कभी भी अपडेट नहीं करना चाहेंगे, और केवल वे पिछले संस्करणों को जोड़ना चाहते हैं। इसके अलावा 'संस्करण' डोमेन ऑब्जेक्ट काफी जटिल है और इसे पुनर्प्राप्त करने के लिए भारी डेटाबेस पहुंच का कारण बनता है।हाइबरनेट - पूरे संग्रह

जब मेरे पास इनमें से किसी एक ऑब्जेक्ट का नया संस्करण है, तो मैं इसे पूरे सेट को लोड किए बिना दूसरों के साथ सहेजना चाहता हूं।

क्यों हाइबरनेट हमेशा एक संग्रह को प्रारंभ करता है जब मैं केवल जोड़ सकते हैं या एक तत्व निकालना चाहते हैं: उन्नत पूछे जाने वाले प्रश्न इस पर कुछ सलाह है?

दुर्भाग्य से संग्रह API विधि वापसी मान को परिभाषित करता है जिसे केवल डेटाबेस को मारकर गणना की जा सकती है। इसमें तीन अपवाद हैं: हाइबरनेट <bag>, <idbag> या <list> में inverse="true" के साथ संग्रह को आरंभ किए बिना घोषित कर सकता है; वापसी मूल्य हमेशा सच होना चाहिए।

आप अतिरिक्त डेटाबेस यातायात से बचना चाहते हैं (यानी। प्रदर्शन महत्वपूर्ण कोड में), केवल कई-टू-वन संघों उपयोग करने के लिए अपने मॉडल refactor। यह लगभग हमेशा संभव है। फिर संग्रह पहुंच के स्थान पर प्रश्नों का उपयोग करें।

मैं इन सभी के लिए नया हूं और 100% सुनिश्चित नहीं हूं कि आपके मॉडल को केवल एक-से-एक संगठनों का उपयोग करने के लिए कैसे दोबारा तैयार किया जाए। क्या कोई मुझे एक ट्यूटोरियल में इंगित करने का उदाहरण दे सकता है ताकि मैं सीख सकूं कि यह मेरे मुद्दे को कैसे हल करेगा?

+0

मुझे लगता है कि मुझे वास्तव में क्या चाहिए 1) संग्रह को लोड करने पर केवल मुख्य संशोधन (ऑडिट रिपोर्ट को छोड़कर) को पुनः प्राप्त करने के लिए 'हाइबरनेट फ़िल्टर' का उपयोग करने में सक्षम होना; और फिर 2) यदि यह सिर किसी ऑपरेशन द्वारा संशोधित किया जाता है (संग्रह में दो तत्वों का कारण बनता है) वर्तमान 'सिर' को अपडेट करने के लिए हाइबरनेट को बताएं (जैसे अब सिर नहीं है) और फिर डेटाबेस में नया संस्करण डालना। दुर्भाग्यवश, यदि हम इस दृष्टिकोण को लेते हैं तो हाइबरनेट को लगता है कि फ़िल्टर किए गए तत्व (पिछले संशोधन) अब मूल सेट से जुड़े नहीं हैं। अपरिवर्तनीय = 'सत्य' सेटिंग काम नहीं कर रही है। –

+0

खुशी है कि हम मदद कर सकते हैं। यदि आपको कुछ जवाब पसंद हैं, तो आप उनके समय के लिए लोगों को धन्यवाद देने के लिए उनके लिए वोट दे सकते हैं (शीर्ष पर छोटे तीर दबाएं)। साथ ही, यदि कोई जवाब आपके लिए पर्याप्त है, यदि आप किसी और चीज पर जाते हैं, तो आप एक जवाब को 'स्वीकृत' के रूप में चिह्नित कर सकते हैं। – KLE

उत्तर

8

तरह से मैं आम तौर पर ऐसा करने के "उलटा" के रूप में संग्रह को परिभाषित करने के लिए है।

कि मोटे तौर पर इसका मतलब है: 1-एन संघ के प्राथमिक परिभाषा "एन" अंत में किया जाता है। अगर आप संग्रह में कुछ जोड़ना चाहते हैं तो आप विस्तार डेटा के संबंधित ऑब्जेक्ट को बदल दें।

एक छोटा सा एक्सएमएल उदाहरण:

<class name="common.hibernate.Person" table="person"> 
    <id name="id" type="long" column="PERSON_ID"> 
     <generator class="assigned"/> 
    </id> 
    <property name="name"/> 
    <bag name="addresses" inverse="true"> 
     <key column="PERSON_ID"/> 
     <one-to-many class="common.hibernate.Address"/> 
    </bag> 
</class> 

<class name="common.hibernate.Address" table="ADDRESS"> 
    <id name="id" column="ADDRESS_ID"/> 
    <property name="street"/> 
    <many-to-one name="person" column="PERSON_ID"/> 
    </class> 

तो अद्यतन पता में विशेष रूप से किया जाता है:

Address a = ...; 
a.setPerson(me); 
a.setStreet("abc"); 
Session s = ...; 
s.save(a); 

हो गया। आपने संग्रह को भी स्पर्श नहीं किया। यह विचार करें केवल पढ़ने के लिए, HQL के द्वारा क्वेरी, और पुनरावृत्ति और यह प्रदर्शित करने के लिए बहुत ही व्यावहारिक हो सकता है।

+0

आपके समय और सलाह के लिए बहुत धन्यवाद। यह एक उत्कृष्ट सुझाव है। मैंने इसमें देखा, लेकिन, दुर्भाग्यवश मेरे पास दो विरोधाभासी मुद्दे थे: 1) 'प्रबंधित-उप-घटक' बाहरी प्रणाली से हैं इसलिए मैं उनसे आवश्यक व्यस्त संपर्क नहीं जोड़ सकता; 2) इसके अलावा स्वामित्व वाली इकाई पहले से ही सुपरक्लस में 'प्रबंधित-उप-घटक' के 'प्रकार' की घोषणा करती है जिससे इसे बनाना और इंटरमीडिएट रैपर बनाना मुश्किल हो जाता है। हालांकि, यह सलाह दूसरों के लिए एक समान स्थिति में उपयुक्त होगी। धन्यवाद! –

+0

ए।सेटपर्सन (मुझे) => अब मैं समझता हूँ! धन्यवाद! – Karussell

2

अगर मैं अच्छी तरह से समझ अपनी जरूरत:

  • आप पूरे संग्रह को प्रारंभ करने के बिना कि संग्रह में कोई आइटम जोड़ने के लिए कैसे (में एक में-स्मृति-केवल जोड़ने के अपरिवर्तनीय वस्तुओं
  • का संग्रह है वर्तमान सत्र)?

क्या आपने पर अपने संग्रह को डिस्कनेक्ट किए गए पर विचार किया था?

  • लोड यह एक बार जब आवेदन
  • एक तत्व दो आपरेशन का मतलब होगा, केवल एक ही स्थान पर एक भी सेवा के द्वारा किया जोड़ना शुरू होता है:
    • तत्व (तेजी से डेटाबेस कार्रवाई बचाने के लिए, कोई व्यापक है (कोई डेटाबेस कार्रवाई) माता-पिता के लिए क्या किया)
    • मौजूदा कट संग्रह करने के लिए तत्व जोड़
+0

आपके समय और सलाह के लिए बहुत धन्यवाद। एक शीर्ष स्तर इकाई है कि पिछले और प्रबंधित उप-घटक के वर्तमान संस्करण का एक संग्रह (एक नक्शा) का कहना है है। उपयोगकर्ता वर्तमान प्रबंधित उप-घटक पर मनमाने ढंग से संचालन निर्दिष्ट कर सकता है। यदि इनमें से किसी भी ऑपरेशन के परिणामस्वरूप उप-घटक में संशोधन होता है तो वर्तमान संस्करण पिछले संस्करण और नया बदल दिया संस्करण 'हेड' बनना चाहिए। मैं कैस्केडिंग ऑपरेशन को हटाने और मैन्युअल रूप से इसे संभालने में देखता हूं। धन्यवाद! –

+0

ठीक है, खुशी है कि मैं आपकी मदद कर सकता हूं। – KLE

11

जब आपके पास कोई सूची या सेट-आधारित संग्रह होता है और आप अपने संग्रह में एक नई वस्तु जोड़ते हैं, तो हाइबरनेट हमेशा डेटाबेस को हिट करेगा क्योंकि यह एक ऑब्जेक्ट को सहेजने या अद्यतन करने से पहले बराबर क्रियान्वयन का उपयोग करके तुलना करता है - सेट का उपयोग करते समय - या सूची का उपयोग करते समय इंडेक्स कॉलम की तुलना करके। सेट और सूची अर्थपूर्ण के कारण इस व्यवहार की आवश्यकता है। इसके कारण, आपके आवेदन का प्रदर्शन महत्वपूर्ण रूप से कम हो सकता है कि आपके पास रिकॉर्ड का समूह है या नहीं।

कुछ वैकल्पिक हल एक encapsuled थैला संग्रह के साथ साथ अपने वांछित सेट या सूची एक संपत्ति

@Entity 
public class One { 

    private Collection<Many> manyCollection = new ArrayList<Many>(); 

    @Transient 
    public Set<Many> getManyCollectionAsSet() { return new HashSet<Many>(manyCollection); } 
    public void setManyCollectionAsSet(Set<Many> manySet) { manyCollection = new ArrayList<Many>(manySet); } 

    /** 
     * Keep in mind that, unlike Hibernate, JPA specification does not allow private visibility. You should use public or protected instead 
     */ 
    @OneToMany(cascade=ALL) 
    private Collection<Many> getManyCollection() { return manyCollection; } 
    private void setManyCollection(Collection<Many> manyCollection) { this.manyCollection = manyCollection; } 

} 

उपयोग ManyToOne बजाय OneToMany के रूप में सामने आ रहा का उपयोग करके इस मुद्दे

रूपांतरण पैटर्न काबू पाने के लिए

@Entity 
public class One { 

    /** 
     * Neither cascade nor reference 
     */ 

} 

@Entity 
public class Many { 

    private One one; 

    @ManyToOne(cascade=ALL) 
    public One getOne() { return one; } 
    public void setOne(One one) { this.one = one } 

} 

कैशिंग - जब आपकी आवश्यकताओं के आधार पर लागू किया जाता है, तो आपकी कॉन्फ़िगरेशन आपके एप्लिकेशन के प्रदर्शन को बढ़ा या घटा सकती है। here

4 ° एसक्यूएल बाधा देखें - आप एक संग्रह है कि एक सेट की तरह बर्ताव चाहते हैं, आप किसी SQL बाधा है, जो एक स्तंभ या स्तंभों की सेट करने के लिए लागू किया जा सकता का उपयोग कर सकते हैं। देखें here

+4

मुझे लगता है कि यह जोड़ने के लिए वर्तमान संग्रह को पढ़ता है। ऐसा इसलिए है क्योंकि इसे 'सेट' बाधाओं की जांच करने की आवश्यकता है। यानी यह देखने की ज़रूरत है कि क्या आप जो इकाई जोड़ रहे हैं वह संग्रह में पहले से ही है, क्योंकि इसे पहले से मौजूद होने पर झूठी वापसी करनी है। – davidsheldon

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