2013-02-26 88 views
6

मैं स्प्रिंग/जेपीए/हाइबरनेट करने के लिए नए कर रहा हूँ में विफल रहता है, और यह आसान वास्तविकता लगता है, जबकि अभी नहीं किया गया है। मुझे कुछ मदद इस्तेमाल करनी थी।वसंत-जेपीए: माता पिता इकाई को अद्यतन करने के नए बच्चे संस्थाओं जारी रहती है, उन्हें क्षणिक रूप में व्याख्या बजाय

मेरे पास एक अभिभावक इकाई है जिसमें बाल संस्थाओं की एक सूची है। मैं चर्चा सरल रखने के लिए इन का उपयोग करेंगे:

@Entity 
public class Parent { 
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Long id; 

    @OneToMany(fetch=FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="parent") 
    private List<Child> children= new ArrayList<Child>(); 

    etc... 
} 

@Entity 
public class Child { 
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Long id; 

    @ManyToOne 
    private Parent parent; 

    etc... 
} 

@Repository 
public interface ParentRepository extends JpaRepository<Parent, Long> {}; 

दौर 1, मैं एक नया माता पिता और एक नए बच्चे बनाते हैं, माता पिता की सूची में बच्चे को जोड़ सकते हैं और बच्चे पर माता-पिता की स्थापना की। जब मैं माता-पिता को बचाता हूं तो बच्चा भी बचाया जाता है।

@Transactional(propagation=Propagation.REQUIRES_NEW) 
void update() { 
    Parent parent = repository.findOne(parentID); 
    Child newChild = new Child(); 
    newChild.setParent(parent); 
    parent.add(newChild); 
    parent = repository.save(parent); 
} 

हालांकि, इस समय नए बच्चे कभी नहीं एक समान होती है:

@Transactional(propagation=Propagation.REQUIRES_NEW) 
void create() { 
    Parent parent = new Parent(); 
    Child child = new Child(); 
    parent.add(child); 
    child.setParent(parent); 
    parent = repository.save(parent); 
} 

अब, राउंड 2, मैं एक नया बच्चा जोड़ने!

मैं कोशिश की है सबसे CascadeType, @GeneratedValue GenerationType, @Transactional प्रचार प्रकार के हर भिन्नता ...

हाइबरनेट के माध्यम से इस ट्रेसिंग (दर्दनाक!), यहाँ है कि मैं क्या पाया है:

  • दूसरी बार सहेजते समय, समस्या दूसरे (नए) बच्चे के साथ होती है।
  • मुद्दा यह है कि जब यह माता पिता के बच्चे की सूची नए बच्चे लागू करने के लिए समय आता है EntityManager (अभी तक) में क्षणिक माना में नहीं है और इस तरह लगता है।
  • नतीजतन, यह प्रभावी रूप से अशक्त के रूप में श्रृंखला नीचे पारित किया जा रहा है, तो निम्न में जिसके परिणामस्वरूप:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is 
javax.persistence.RollbackException: Error while committing thetransaction 
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521) 
... 

Caused by: javax.persistence.RollbackException: Error while committing the transaction 
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:92) 
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:512) 
... 

Caused by: org.hibernate.AssertionFailure: collection [null] was not processed by flush() 
    at org.hibernate.engine.spi.CollectionEntry.postFlush(CollectionEntry.java:225) 
... 
  • यह प्रासंगिक हो सकता है कि मेरे वास्तविक कोड "बाल" में बाल संस्थाओं का नक्शा भी है। यह "मूल्य" "क्षणिक" दुरूपयोग के कारण शून्य के रूप में पारित हो जाता है।
  • मैं डिबगिंग के लिए चीजों को सिंक्रोनस रखने के लिए repository.saveAndFlush() का उपयोग कर रहा हूं। जब मैं बस .save() का उपयोग करता हूं, तो मेरे @PreUpdate EntityListener को कॉल किया जाता है लेकिन @PostUpdate श्रोता कभी नहीं होता है।
  • ऐसा लगता है कि अगर बच्चे को लगातार बने रहें या माता-पिता को बनाए रखने से कम से कम एक आईडी दिया जाए तो कोई समस्या नहीं होगी। लेकिन यह मैन्युअल रूप से ऐसा करने के लिए काउंटर-उत्पादक भी लगता है। फिर भी, यह एकमात्र विकल्प है जिसके बारे में मैं सोच सकता हूं।

पढ़ने के लिए धन्यवाद। कोई भी सहायताकाफी प्रशंसनीय होगी!

+0

दुर्भाग्यवश हम आपके स्टैकट्रैक में नहीं देखते हैं जो संग्रह शून्य है। क्या यह हो सकता है कि मानचित्र आपके बच्चे में प्रारंभिक नहीं है? क्या आप परीक्षण विशेषता को सीधे हल करने के लिए फील्ड एट्रिब्यूट को नया हैशैप असाइन करने का प्रयास कर सकते हैं? हाइबरनेट में नल संग्रह के साथ कुछ quirks है। यह सुनिश्चित करने का प्रयास करें कि संग्रह शून्य नहीं हैं और आपके परीक्षण को दोबारा शुरू करें। –

+0

मार्टिन के जवाब देने के लिए धन्यवाद। नल बच्चे का बच्चा है। ऑब्जेक्ट में यह एक मानचित्र है जिसमें इसमें ऑब्जेक्ट हैं। हालांकि, जब माता-पिता को जारी रखा जा रहा है, तो हाइबरनेट बच्चे को देखता है, इसे EntityManager में नहीं देखता है, यह तय करता है कि यह क्षणिक होना चाहिए और इसलिए यह अपना मान शून्य पर सेट करता है (पहचान मानचित्र में, मूल वस्तु नहीं)। क्या हाइबरनेट को विशेष रूप से नक्शे के साथ कोई समस्या है? – Didjit

+1

हाइबरनेट को संग्रह के साथ कोई समस्या होने के लिए बहुत कुछ कहना होगा। लेकिन संग्रह को संभालने में मुश्किल हो सकती है। जब हम कुछ संग्रहों को पूरी तरह से बदल देते हैं तो हम अनाथ हटाने (= सत्य) के साथ कुछ परेशानी में भाग गए। हमारे लिए भाग्यशाली इन चीजों को आम तौर पर लोगों और दस्तावेज़ीकरण द्वारा वर्णित किया जाता है और जब आप जानते हैं कि क्या खोजना है तो हमने इसे तेज़ी से हल किया है। मूल रूप से आपको संग्रह होने के बाद संग्रह को पुन: प्रारंभ नहीं करना चाहिए बल्कि इसके बजाय स्पष्ट उपयोग करना चाहिए। Thats क्यों मुझे आपकी समस्या के लिए यह विचार था। ए, बी और सी के साथ टेस्टकेस बनाने और अपनी समस्या की पहचान करने के लिए इसे चलाने के लिए सबसे आसान हो सकता है। –

उत्तर

3

मैं इस समस्या पाया है, हालांकि मैं वास्तव में अभी तक एक पूर्ण समाधान नहीं है।

सबसे पहले, कुछ अतिरिक्त पृष्ठभूमि। माता-पिता और बच्चे के अलावा, मेरे पास एक संबंधित वर्ग था जिसे मैं यहां "हाउस" कहूंगा।हाउस में एक EntityListener परिभाषित किया गया है ताकि जब इसे सहेजा/अपडेट किया जाए, संबंधित माता-पिता & बाल ऑब्जेक्ट्स को बनाया/अपडेट किया जाता है। तो यह हाउस के पोस्टपर्सिस्ट/पोस्टअपडेट के दौरान है कि माता-पिता और बाल वस्तुओं को बनाया गया है, लिंक किया गया है, सदन की ओर इशारा किया गया है, और फिर जारी है।

तो ऐसा लगता है कि हाउस लेनदेन पूरा होने से पहले ऐसा किया जाता है। हाउस गतिविधि पूरी होने तक केवल माता-पिता/बाल गतिविधि को खींचकर, सभी समस्याएं चली गईं।

केवल एक चीज जिसे मैं समझ सकता हूं (मैं थोड़ा गहरा खोदूँगा) यह है कि चूंकि सदन उस समय पूरी तरह से जारी नहीं रहा है, इसके परिणामस्वरूप ऊपर वर्णित क्षणिक स्थिति में परिणाम होता है।

अद्यतन:

चाक अज्ञान अप करने के लिए एक। स्पष्ट रूप से EntityCallback विधियां "should not call EntityMan­ager or Query methods and should not access any other entity objects." उसे नहीं पता था। यह अब सवाल उठाता है कि कैसे मुझे किसी अन्य गतिविधि पर एक इकाई की रचना को ट्रिगर करना चाहिए। लेकिन अगर आवश्यक हो तो मैं इसके लिए एक और धागा शुरू करूंगा। सबको शुक्रीया!

+1

+1: अच्छा काम जवाब खोदना। आम तौर पर, इस तरह के इकाई संबंध तार्किक हैं और इस प्रकार आपके कोड में मॉडलिंग किया जाना चाहिए जहां अन्य सभी तर्क रहते हैं। श्रोता में ऐसा करने की कोशिश करना एक ही चीज़ करने के लिए डेटाबेस ट्रिगर लिखने की कोशिश करने के समान है। आप डेटाबेस में उस तर्क को नहीं चाहते हैं, तो आप इसे दृढ़ता ढांचे में क्यों बनाना चाहते हैं? –

3

तुम क्या दिखाया है में सब कुछ, सुंदर सामान्य लगती है तो समस्या यह है कि नक्शा आप का उल्लेख में झूठ हो सकता है। मेरे पास गीथूब पर working example of a bidirectional one-to-many using Spring Data JPA है। आप कोड या क्लोन के माध्यम से देखने के लिए और के साथ इसे चला सकते हैं:

git clone git://github.com/zzantozz/testbed tmp 
cd tmp/spring-data 
mvn -q compile exec:java -D exec.mainClass=rds.springdata.JpaBiDiOneToManyExample 
+0

धन्यवाद, रयान। मैं एक नज़र डालूंगा और वापस आऊंगा। – Didjit

+0

ठीक है, रयान। मैंने सुनिश्चित किया कि मेरी कक्षाएं आपके साथ मिलें और अभी भी समस्याएं हों। लेकिन अगर मैंने सभी "तंत्र" को हटा दिया और मैन्युअल रूप से बनाया, जोड़ा, और सहेजा - मेरी वस्तुओं ने ठीक काम किया। मैंने जो खोजा है उसके बारे में नीचे मेरा उत्तर देखें। और नमूना कोड बनाने में आपके द्वारा किए गए काम के लिए फिर से धन्यवाद। यह बहुत सराहना की थी! दुर्भाग्यवश, मैं यहां इतना नया हूं कि मैं आपको +1 नहीं कर सकता, लेकिन यह भावना में है! – Didjit