EntityManager.merge()
नई वस्तुओं को सम्मिलित कर सकते हैं और मौजूदा अपडेट कर सकते हैं।
कोई क्यों उपयोग करना चाहेगा persist()
(जो केवल नई वस्तुएं बना सकता है)?
EntityManager.merge()
नई वस्तुओं को सम्मिलित कर सकते हैं और मौजूदा अपडेट कर सकते हैं।
कोई क्यों उपयोग करना चाहेगा persist()
(जो केवल नई वस्तुएं बना सकता है)?
जवाबों:
किसी भी तरह से एक इकाई को PersistenceContext में जोड़ा जाएगा, अंतर यह है कि आप इकाई के साथ क्या करते हैं।
Persist एक इकाई उदाहरण लेता है, इसे संदर्भ में जोड़ता है और उस उदाहरण को प्रबंधित करता है (यानी इकाई के लिए भविष्य के अपडेट को ट्रैक किया जाएगा)।
मर्ज उस प्रबंधित उदाहरण को लौटाता है जिसे राज्य में विलय कर दिया गया था। यह कुछ ऐसा है जो PersistenceContext में मौजूद है या आपकी इकाई का एक नया उदाहरण बनाता है। किसी भी स्थिति में, यह राज्य को आपूर्ति की गई इकाई से कॉपी करेगा, और प्रबंधित प्रतिलिपि लौटाएगा। आपके द्वारा पास किया जाने वाला उदाहरण प्रबंधित नहीं किया जाएगा (आपके द्वारा किए गए कोई भी परिवर्तन लेन-देन का हिस्सा नहीं होगा - जब तक कि आप फिर से मर्ज न कहें)। आप उपयोग किए गए रिटर्न इंस्टेंस (प्रबंधित एक) के माध्यम से कर सकते हैं।
शायद एक कोड उदाहरण मदद करेगा।
MyEntity e = new MyEntity();
// scenario 1
// tran starts
em.persist(e);
e.setSomeField(someValue);
// tran ends, and the row for someField is updated in the database
// scenario 2
// tran starts
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue);
// tran ends but the row for someField is not updated in the database
// (you made the changes *after* merging)
// scenario 3
// tran starts
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue);
// tran ends and the row for someField is updated
// (the changes were made to e2, not e)
परिदृश्य 1 और 3 लगभग बराबर हैं, लेकिन कुछ परिस्थितियां हैं जहां आप परिदृश्य 2 का उपयोग करना चाहते हैं।
merge
प्रदर्शन के हिट होने से पहले किसी वस्तु की शायद पूरी प्रतिलिपि?
@GeneratedId
क्या मैं इसे परिदृश्य 2 में प्राप्त कर सकता हूं?
दृढ़ता और मर्ज दो अलग-अलग उद्देश्यों के लिए हैं (वे सभी विकल्प नहीं हैं)।
(अंतर की जानकारी का विस्तार करने के लिए संपादित)
जारी रहती है:
विलय:
दृढ़ता () दक्षता:
दृढ़ता () शब्दार्थ:
उदाहरण:
{
AnyEntity newEntity;
AnyEntity nonAttachedEntity;
AnyEntity attachedEntity;
// Create a new entity and persist it
newEntity = new AnyEntity();
em.persist(newEntity);
// Save 1 to the database at next flush
newEntity.setValue(1);
// Create a new entity with the same Id than the persisted one.
AnyEntity nonAttachedEntity = new AnyEntity();
nonAttachedEntity.setId(newEntity.getId());
// Save 2 to the database at next flush instead of 1!!!
nonAttachedEntity.setValue(2);
attachedEntity = em.merge(nonAttachedEntity);
// This condition returns true
// merge has found the already attached object (newEntity) and returns it.
if(attachedEntity==newEntity) {
System.out.print("They are the same object!");
}
// Set 3 to value
attachedEntity.setValue(3);
// Really, now both are the same object. Prints 3
System.out.println(newEntity.getValue());
// Modify the un attached object has no effect to the entity manager
// nor to the other objects
nonAttachedEntity.setValue(42);
}
इस तरह केवल इकाई प्रबंधक में किसी भी रजिस्टर के लिए 1 संलग्न वस्तु मौजूद है।
एक इकाई के लिए मर्ज () एक आईडी के साथ कुछ इस प्रकार है:
AnyEntity myMerge(AnyEntity entityToSave) {
AnyEntity attached = em.find(AnyEntity.class, entityToSave.getId());
if(attached==null) {
attached = new AnyEntity();
em.persist(attached);
}
BeanUtils.copyProperties(attached, entityToSave);
return attached;
}
हालाँकि, यदि MySQL मर्ज () से कनेक्ट किया जा सकता है, तो DUPLICATE KEY UPDATE विकल्प के साथ INSERT पर कॉल का उपयोग करते हुए दृढ़ता () का उपयोग किया जा सकता है, JPA एक बहुत ही उच्च स्तरीय प्रोग्रामिंग है और आप यह नहीं मान सकते कि यह हर जगह होने वाला है।
em.persist(x)
करना मान्य नहीं है x = em.merge(x)
?
merge()
यह भी एक फेंक कर सकते हैंEntityExistsException
RuntimeException
, लेकिन इसका जवादोक में उल्लेख नहीं है।
यदि आप असाइन किए गए जनरेटर का उपयोग कर रहे हैं, तो हठ के बजाय मर्ज का उपयोग करना अनावश्यक SQL कथन का कारण बन सकता है , इसलिए प्रदर्शन को प्रभावित कर रहा है।
इसके अलावा, प्रबंधित संस्थाओं के लिए कॉल मर्ज करना भी एक गलती है क्योंकि प्रबंधित इकाइयाँ स्वचालित रूप से हाइबरनेट द्वारा प्रबंधित की जाती हैं और उनके राज्य को पर्सेंटेंस कॉन्सेप्ट को फ्लश करने पर गंदे चेकिंग तंत्र द्वारा डेटाबेस रिकॉर्ड के साथ सिंक्रनाइज़ किया जाता है ।
यह समझने के लिए कि यह सब कैसे काम करता है, आपको पहले यह पता होना चाहिए कि हाइबरनेट SQL स्टेटमेंट से इकाई स्थिति में डेवलपर की मानसिकता को स्थानांतरित करता है ।
हाइबरनेट द्वारा एक इकाई को सक्रिय रूप से प्रबंधित करने के बाद, सभी परिवर्तन डेटाबेस में स्वचालित रूप से प्रचारित होने जा रहे हैं।
हाइबरनेट मॉनिटर वर्तमान में संलग्न इकाइयाँ हैं। लेकिन एक इकाई को प्रबंधित करने के लिए, यह सही इकाई स्थिति में होना चाहिए।
जेपीए की स्थिति को बेहतर ढंग से समझने के लिए, आप निम्नलिखित चित्र की कल्पना कर सकते हैं:
या यदि आप हाइबरनेट विशिष्ट API का उपयोग करते हैं:
उपरोक्त आरेखों के अनुसार, एक इकाई निम्नलिखित चार राज्यों में से एक में हो सकती है:
नया (क्षणिक)
एक नई बनाई गई वस्तु जो कभी भी एक हाइबरनेट Session
(उर्फ Persistence Context
) के साथ संबद्ध नहीं हुई है और किसी भी डेटाबेस तालिका पंक्ति में मैप नहीं की गई है जिसे नई (क्षणिक) स्थिति में माना जाता है।
बने रहने के लिए हमें या तो स्पष्ट रूप से EntityManager#persist
विधि की आवश्यकता होती है या सकर्मक दृढ़ता का उपयोग करना चाहिए।
स्थायी (प्रबंधित)
एक स्थायी इकाई को डेटाबेस तालिका पंक्ति के साथ जोड़ा गया है और इसे वर्तमान में चल रहे परिप्रेक्ष्य द्वारा प्रबंधित किया जा रहा है। ऐसी इकाई में किए गए किसी भी परिवर्तन को डेटाबेस में (सत्र फ्लश-टाइम के दौरान) पहचाना और प्रचारित किया जा रहा है। हाइबरनेट के साथ, हमें अब INSERT / UPDATE / DELETE कथनों को निष्पादित नहीं करना है। हाइबरनेट एक व्यवहारिक लिखने के पीछे काम करने की शैली को नियोजित करता है और वर्तमान Session
फ्लश-टाइम के दौरान परिवर्तनों को अंतिम अंतिम क्षण में सिंक्रनाइज़ किया जाता है ।
जुदा जुदा
एक बार वर्तमान में चल रहे पर्सेंटेज कॉन्सेप्ट को बंद करने के बाद सभी पहले से प्रबंधित इकाइयां अलग हो जाती हैं। क्रमिक परिवर्तनों को अब ट्रैक नहीं किया जाएगा और कोई स्वचालित डेटाबेस सिंक्रनाइज़ेशन नहीं होने वाला है।
एक अलग इकाई को सक्रिय हाइबरनेट सत्र में जोड़ने के लिए, आप निम्नलिखित विकल्पों में से एक चुन सकते हैं:
reattaching
हाइबरनेट (लेकिन जेपीए 2.1 नहीं) सत्र # अद्यतन विधि के माध्यम से रीटेटिंग का समर्थन करता है। एक हाइबरनेट सत्र किसी दिए गए डेटाबेस पंक्ति के लिए केवल एक एंटिटी ऑब्जेक्ट को जोड़ सकता है। ऐसा इसलिए है क्योंकि पर्सेंटेज कॉन्सेप्ट एक इन-मेमोरी कैश (प्रथम स्तर कैश) के रूप में कार्य करता है और केवल एक मान (इकाई) एक दिए गए कुंजी (इकाई प्रकार और डेटाबेस पहचानकर्ता) के साथ जुड़ा हुआ है। एक इकाई को केवल तब ही रिलेटेड किया जा सकता है जब कोई अन्य JVM ऑब्जेक्ट (समान डेटाबेस पंक्ति से मेल खाते हुए) पहले से ही मौजूदा हाइबरनेट सत्र के साथ जुड़ा हुआ हो।
विलय
मर्ज किसी निकाय निकाय स्थिति (स्रोत) की प्रतिलिपि किसी प्रबंधित निकाय आवृत्ति (गंतव्य) पर करने जा रहा है। यदि वर्तमान सत्र में विलय इकाई के समतुल्य नहीं है, तो डेटाबेस से एक प्राप्त किया जाएगा। मर्ज किए गए ऑपरेशन के बाद भी अलग किए गए ऑब्जेक्ट का उदाहरण अलग रखा जाएगा।
हटा दिया
यद्यपि जेपीए मांग करता है कि प्रबंधित इकाइयां केवल हटाने की अनुमति दी जाती हैं, हाइबरनेट भी अलग-अलग संस्थाओं को हटा सकता है (लेकिन केवल एक सत्र # हटाएं विधि कॉल के माध्यम से)। हटाए गए निकाय को केवल हटाने के लिए निर्धारित किया गया है और सत्र डेटाबेस फ्लश-टाइम के दौरान वास्तविक डेटाबेस DELETE स्टेटमेंट निष्पादित किया जाएगा।
मैंने देखा कि जब मैंने उपयोग किया था em.merge
, तो मुझे SELECT
हर एक के लिए एक बयान मिला INSERT
, यहां तक कि जब कोई क्षेत्र नहीं था कि जेपीए मेरे लिए पैदा कर रहा था - प्राथमिक कुंजी क्षेत्र एक यूयूआईडी था जिसे मैंने खुद सेट किया था। मैं स्विच किया em.persist(myEntityObject)
और INSERT
फिर सिर्फ बयान मिला ।
merge()
। मेरे पास जटिल दृश्य के साथ PostgreSQL डेटाबेस था : दृश्य कई तालिकाओं से डेटा एकत्र किया गया था (तालिकाओं में समान संरचना लेकिन अलग-अलग नाम थे)। तो जेपीए ने करने की कोशिश की merge()
, लेकिन वास्तव में जेपीए ने पहली बार बनाया SELECT
(डेटाबेस के कारण सेटिंग्स अलग-अलग तालिकाओं से एक ही प्राथमिक के साथ कई रिकॉर्ड वापस कर सकती है!), फिर जेपीए (हाइबरनेट एक कार्यान्वयन था) विफल: एक ही कुंजी के साथ कई रिकॉर्ड हैं ( org.hibernate.HibernateException: More than one row with the given identifier was found
)। मेरे मामले में मेरी persist()
मदद की।
जेपीए विनिर्देश निम्नलिखित के बारे में कहता है persist()
।
यदि एक्स एक अलग वस्तु है, तो
EntityExistsException
जब निरंतर ऑपरेशन का आह्वान किया जाता है, तो उसे फेंक दिया जा सकता है ,EntityExistsException
या किसी अन्यPersistenceException
को फ्लश या प्रतिबद्ध समय पर फेंक दिया जा सकता है।
अतः उपयोग persist()
करना तब उचित होगा जब ऑब्जेक्ट को अलग की गई वस्तु नहीं होना चाहिए । आप कोड को फेंकना पसंद कर सकते हैं PersistenceException
ताकि यह तेजी से विफल हो जाए।
हालांकि विनिर्देश स्पष्ट नहीं है , एक वस्तु persist()
के @GeneratedValue
@Id
लिए निर्धारित कर सकता है । merge()
हालांकि @Id
पहले से उत्पन्न एक वस्तु होनी चाहिए ।
merge()
हालांकि @Id
पहले से उत्पन्न एक वस्तु होनी चाहिए । " जब भी EntityManager को ऑब्जेक्ट ID के फ़ील्ड के लिए कोई मान नहीं मिलता है, तो उसे DB में जारी (सम्मिलित) किया जाता है।
मर्ज के बारे में कुछ और जानकारी जो आपको दृढ़ता से मर्ज का उपयोग करने में मदद करेगी:
मूल इकाई के अलावा किसी प्रबंधित उदाहरण को वापस करना मर्ज प्रक्रिया का एक महत्वपूर्ण हिस्सा है। यदि समान पहचानकर्ता के साथ एक इकाई उदाहरण पहले से ही दृढ़ता के संदर्भ में मौजूद है, तो प्रदाता अपने राज्य को उस इकाई की स्थिति के साथ अधिलेखित कर देगा जिसे विलय किया जा रहा है, लेकिन प्रबंधित संस्करण जो पहले से मौजूद है, उसे ग्राहक को वापस करना होगा ताकि यह हो सके उपयोग किया गया। अगर प्रदाता ने दृढ़ता के संदर्भ में कर्मचारी उदाहरण को अद्यतन नहीं किया, तो उस उदाहरण का कोई भी संदर्भ नए राज्य में विलय होने के साथ असंगत हो जाएगा।
जब किसी नई इकाई पर मर्ज () किया जाता है, तो यह दृढ़ता () संचालन के समान होता है। यह अस्तित्व के संदर्भ में इकाई को जोड़ता है, लेकिन मूल इकाई उदाहरण को जोड़ने के बजाय, यह एक नई प्रतिलिपि बनाता है और इसके बजाय उस आवृत्ति का प्रबंधन करता है। मर्ज () ऑपरेशन द्वारा बनाई गई प्रतिलिपि इस तरह से बनी रहती है जैसे कि उस पर बनी रहती है।
रिश्तों की उपस्थिति में, मर्ज () ऑपरेशन प्रबंधित इकाई को अद्यतन करने का प्रयास करेगा निकाले गए इकाई द्वारा संदर्भित संस्थाओं के प्रबंधित संस्करणों को इंगित करने के लिए। यदि इकाई का किसी ऐसी वस्तु से संबंध है जिसकी कोई निरंतर पहचान नहीं है, तो मर्ज ऑपरेशन का परिणाम अपरिभाषित है। कुछ प्रदाता प्रबंधित प्रतिलिपि को गैर-स्थायी ऑब्जेक्ट को इंगित करने की अनुमति दे सकते हैं, जबकि अन्य तुरंत एक अपवाद फेंक सकते हैं। मर्ज () ऑपरेशन को इन मामलों में वैकल्पिक रूप से कैस्केड किया जा सकता है ताकि अपवाद को रोका जा सके। हम इस खंड में बाद में मर्ज () ऑपरेशन के कैस्केडिंग को कवर करेंगे। यदि किसी निकाय को निकाय में विलय किया जा रहा है, तो अवैध अवैध अपवाद को फेंक दिया जाएगा।
मर्ज ऑपरेशन में आलसी-लोडिंग संबंध एक विशेष मामला है। यदि किसी आलसी-लोडिंग संबंध को निकाले जाने से पहले किसी इकाई पर ट्रिगर नहीं किया गया था, तो उस संबंध को अनदेखा कर दिया जाएगा जब इकाई का विलय हो जाएगा। यदि रिश्ते को प्रबंधित करते समय ट्रिगर किया गया था और फिर इकाई को अलग करने के दौरान शून्य पर सेट किया गया था, तो इकाई के प्रबंधित संस्करण को इसी तरह मर्ज के दौरान रिश्ते को मंजूरी दे दी जाएगी। "
उपरोक्त सभी जानकारी माइक कीथ और मेरिक श्निकारील द्वारा "प्रो जेपीए 2 मास्टरींग द जावा ™ पर्सिस्टेंस एपीआई" से ली गई थी। अध्याय 6. खंड टुकड़ी और विलय। यह पुस्तक वास्तव में लेखकों द्वारा जेपीए को समर्पित एक दूसरी पुस्तक है। इस नई किताब में कई नई जानकारियां हैं, फिर पूर्व की। मैं वास्तव में उन लोगों के लिए इस पुस्तक को पढ़ने के लिए फिर से तैयार हुआ जो जेपीए के साथ गंभीर रूप से शामिल होंगे। मुझे अपना पहला उत्तर पोस्ट करने के लिए खेद है
वहाँ के बीच कुछ और मतभेद हैं merge
और persist
(मैं फिर से उन पहले से ही यहां पोस्ट करके बताना होगा):
डी 1। merge
पारित इकाई को प्रबंधित नहीं करता है, बल्कि एक और उदाहरण देता है जिसे प्रबंधित किया जाता है। persist
दूसरी तरफ पारित इकाई को प्रबंधित करेगा:
//MERGE: passedEntity remains unmanaged, but newEntity will be managed
Entity newEntity = em.merge(passedEntity);
//PERSIST: passedEntity will be managed after this
em.persist(passedEntity);
डी 2। यदि आप किसी निकाय को हटाते हैं और फिर इकाई को वापस बनाए रखने का निर्णय लेते हैं, तो आप ऐसा केवल दृढ़ता () के साथ कर सकते हैं, क्योंकि merge
फेंक देंगे IllegalArgumentException
।
डी 3। यदि आपने अपनी आईडी (जैसे यूयूआईडी का उपयोग करके) मैन्युअल रूप से देखभाल करने का फैसला किया है, तो एक merge
ऑपरेशन बाद के SELECT
प्रश्नों को ट्रिगर करेगा ताकि उस आईडी के साथ मौजूद संस्थाओं की तलाश की persist
जा सके , जबकि उन प्रश्नों की आवश्यकता नहीं हो सकती है।
D4। ऐसे मामले हैं जब आप बस उस कोड पर भरोसा नहीं करते हैं जो आपके कोड को कॉल करता है, और यह सुनिश्चित करने के लिए कि कोई डेटा अपडेट नहीं किया गया है, बल्कि डाला गया है, आपको उपयोग करना होगा persist
।
मुझे अपनी इकाई पर आलसी अपवाद मिल रहे थे क्योंकि मैं एक आलसी लोड संग्रह तक पहुंचने की कोशिश कर रहा था जो सत्र में था।
मैं एक अलग अनुरोध में क्या करूंगा, सत्र से इकाई को पुनः प्राप्त करता हूं और फिर अपने jsp पृष्ठ पर एक संग्रह तक पहुंचने का प्रयास करता हूं जो समस्याग्रस्त था।
इसे समाप्त करने के लिए, मैंने अपने नियंत्रक में एक ही इकाई को अद्यतन किया और इसे अपने जेएसपी को पारित कर दिया, हालांकि मुझे लगता है कि जब मैंने सत्र में फिर से बचाया कि यह भी सुलभ होगा SessionScope
और एक नहीं फेंकेगा LazyLoadingException
, उदाहरण 2 का एक संशोधन:
निम्नलिखित ने मेरे लिए काम किया है:
// scenario 2 MY WAY
// tran starts
e = new MyEntity();
e = em.merge(e); // re-assign to the same entity "e"
//access e from jsp and it will work dandy!!
मुझे यह स्पष्टीकरण हाइबरनेट डॉक्स के ज्ञानवर्धक से मिला, क्योंकि उनमें उपयोग का मामला है:
मर्ज का उपयोग और शब्दार्थ () नए उपयोगकर्ताओं के लिए भ्रमित करने वाला प्रतीत होता है। सबसे पहले, जब तक आप किसी अन्य इकाई प्रबंधक में एक इकाई प्रबंधक में लोड की गई वस्तु स्थिति का उपयोग करने का प्रयास नहीं कर रहे हैं, तब तक आपको मर्ज () का उपयोग करने की आवश्यकता नहीं है । कुछ पूरे अनुप्रयोग इस पद्धति का उपयोग कभी नहीं करेंगे।
आमतौर पर मर्ज () का उपयोग निम्नलिखित परिदृश्य में किया जाता है:
- अनुप्रयोग पहले निकाय प्रबंधक में किसी ऑब्जेक्ट को लोड करता है
- ऑब्जेक्ट को प्रेजेंटेशन लेयर तक पहुंचाया जाता है
- कुछ संशोधन वस्तु के लिए किए जाते हैं
- ऑब्जेक्ट को व्यावसायिक लॉजिक परत पर वापस भेज दिया जाता है
- एप्लिकेशन दूसरी इकाई प्रबंधक में मर्ज () कॉल करके इन संशोधनों को जारी रखता है
यहाँ मर्ज का सटीक शब्दार्थ है ():
- यदि एक ही पहचानकर्ता के साथ एक प्रबंधित उदाहरण है जो वर्तमान में दृढ़ता के संदर्भ में जुड़ा हुआ है, तो दिए गए ऑब्जेक्ट की स्थिति को प्रबंधित उदाहरण पर कॉपी करें
- यदि वर्तमान में दृढ़ता प्रसंग से जुड़ा कोई प्रबंधित उदाहरण नहीं है, तो इसे डेटाबेस से लोड करने का प्रयास करें, या एक नया प्रबंधित उदाहरण बनाएं
- प्रबंधित उदाहरण वापस आ गया है
- दिए गए उदाहरण हठ प्रसंग से जुड़े नहीं हैं, यह अलग रहता है और आमतौर पर खारिज कर दिया जाता है
से: http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/objectstate.html
उत्तरों के माध्यम से जाने से `कैस्केड 'और आईडी जनरेशन के बारे में कुछ विवरण गायब हैं। प्रश्न देखें
इसके अलावा, यह ध्यान देने योग्य है कि आपके पास Cascade
विलय और अनुशीलन के लिए अलग-अलग एनोटेशन हो सकते हैं : Cascade.MERGE
और Cascade.PERSIST
जिनका इस्तेमाल विधि के अनुसार किया जाएगा।
युक्ति आपका मित्र है;)
जावा प्लेटफॉर्म पर निर्मित एंटरप्राइज़ अनुप्रयोगों के क्षेत्र में जेपीए निर्विवाद रूप से एक महान सरलीकरण है। एक डेवलपर के रूप में जिसे जे 2 ईई में पुरानी इकाई बीन्स की पेचीदगियों से जूझना पड़ा, मैं जावा ईई विनिर्देशों के बीच जेपीए को शामिल करने को एक बड़ी छलांग के रूप में देखता हूं। हालाँकि, जेपीए के विवरणों में गहराई से जाने के दौरान मुझे ऐसी चीजें मिलती हैं जो इतनी आसान नहीं हैं। इस लेख में मैं EntityManager के मर्ज की तुलना करता हूं और उन तरीकों को जारी रखता हूं जिनके अतिव्यापी व्यवहार के कारण न केवल एक नौसिखिया के लिए भ्रम पैदा हो सकता है। इसके अलावा मैं एक सामान्यीकरण का प्रस्ताव करता हूं जो दोनों तरीकों को एक अधिक सामान्य विधि के विशेष मामलों के रूप में देखता है।
स्थायी इकाइयाँ
मर्ज विधि के विपरीत हठ विधि बहुत सरल और सहज है। दृढ़ता विधि के उपयोग का सबसे सामान्य परिदृश्य निम्नानुसार अभिव्यक्त किया जा सकता है:
"इकाई वर्ग का एक नया बनाया गया उदाहरण स्थायी विधि को दिया जाता है। इस पद्धति के वापस आने के बाद, इकाई को प्रबंधित किया जाता है और डेटाबेस में प्रविष्टि के लिए योजना बनाई जाती है। यह लेनदेन शुरू होने से पहले या फ्लश विधि कहे जाने पर या उससे पहले हो सकता है। यदि इकाई PERSIST झरना रणनीति के साथ चिह्नित रिश्ते के माध्यम से किसी अन्य इकाई का संदर्भ देती है, तो यह प्रक्रिया उस पर भी लागू होती है। "
हालांकि, विवरण अधिक विवरण में जाते हैं, हालांकि, उन्हें याद रखना महत्वपूर्ण नहीं है क्योंकि ये विवरण केवल अधिक या कम विदेशी स्थितियों को कवर करते हैं।
संस्थाओं को विलय करना
दृढ़ता की तुलना में, मर्ज के व्यवहार का वर्णन इतना सरल नहीं है। कोई मुख्य परिदृश्य नहीं है, क्योंकि यह जारी रहने की स्थिति में है, और एक प्रोग्रामर को एक सही कोड लिखने के लिए सभी परिदृश्यों को याद रखना चाहिए। मुझे ऐसा लगता है कि जेपीए डिजाइनर कुछ ऐसा तरीका चाहते थे, जिसकी प्राथमिक चिंता अलग-थलग पड़ने वाली संस्थाओं को संभालना होगा (जैसा कि दृढ़ता से बनी विधि जो मुख्य रूप से नव निर्मित संस्थाओं से संबंधित है।) मर्ज विधि का प्रमुख कार्य राज्य को एक से स्थानांतरित करना है। अप्रबंधित इकाई (तर्क के रूप में पारित) दृढ़ता संदर्भ के भीतर अपने प्रबंधित समकक्ष के लिए। हालाँकि, यह कार्य कई परिदृश्यों में विभाजित है, जो समग्र विधि के व्यवहार की समझदारी को खराब करता है।
जेपीए विनिर्देश से पैराग्राफ को दोहराने के बजाय मैंने एक प्रवाह आरेख तैयार किया है जो योजनाबद्ध रूप से मर्ज के व्यवहार को दर्शाता है:
तो, मुझे कब उपयोग करना चाहिए और कब विलय करना चाहिए?
दृढ़ रहना
मर्ज
परिदृश्य X:
टेबल: स्पिटर (एक), टेबल: स्पिटल्स (कई) (स्पिटल्स एक FK: spitter_id के साथ संबंध के मालिक हैं)
इस परिदृश्य के परिणामस्वरूप बचत होती है: स्पिटर और स्पिटल्स दोनों जैसे कि समान स्पिटर के स्वामित्व में हो।
Spitter spitter=new Spitter();
Spittle spittle3=new Spittle();
spitter.setUsername("George");
spitter.setPassword("test1234");
spittle3.setSpittle("I love java 2");
spittle3.setSpitter(spitter);
dao.addSpittle(spittle3); // <--persist
Spittle spittle=new Spittle();
spittle.setSpittle("I love java");
spittle.setSpitter(spitter);
dao.saveSpittle(spittle); //<-- merge!!
परिदृश्य Y:
यह स्पिटर को बचाएगा, 2 स्पिटल्स को बचाएगा, लेकिन वे समान स्पिटर को संदर्भित नहीं करेंगे!
Spitter spitter=new Spitter();
Spittle spittle3=new Spittle();
spitter.setUsername("George");
spitter.setPassword("test1234");
spittle3.setSpittle("I love java 2");
spittle3.setSpitter(spitter);
dao.save(spittle3); // <--merge!!
Spittle spittle=new Spittle();
spittle.setSpittle("I love java");
spittle.setSpitter(spitter);
dao.saveSpittle(spittle); //<-- merge!!
एक और अवलोकन:
merge()
केवल एक ऑटो-जनरेटेड आईडी (पर परीक्षण किया गया ) IDENTITY
और SEQUENCE
इस तरह की आईडी के साथ रिकॉर्ड आपके टेबल में पहले से मौजूद है। उस स्थिति merge()
में रिकॉर्ड को अपडेट करने का प्रयास करेंगे। यदि, हालांकि, एक आईडी अनुपस्थित है या किसी भी मौजूदा रिकॉर्ड से मेल नहीं खा रहा है, तो merge()
इसे पूरी तरह से अनदेखा कर देगा और एक डीबी को एक नया आवंटित करने के लिए कहेगा। यह कभी-कभी बहुत सारे कीड़े का स्रोत होता है। merge()
एक नए रिकॉर्ड के लिए एक आईडी को मजबूर करने के लिए उपयोग न करें ।
persist()
दूसरी ओर आपको कभी भी एक आईडी पास नहीं करने देगा। यह तुरंत विफल हो जाएगा। मेरे मामले में, यह है:
इसके कारण: org.hibernate.PersistentObjectException: अलग की गई इकाई बनी रहती है
हाइबरनेट-जेपा जेवाडोक में एक संकेत है:
फेंकता है : javax.persistence.EntityExistsException - यदि इकाई पहले से मौजूद है। (यदि इकाई पहले से मौजूद है, तो जारी रखने के ऑपरेशन को लागू करने पर EntityExistsException को फेंक दिया जा सकता है, या EntityExistsException या किसी अन्य PersistenceException को फ्लश या प्रतिबद्ध समय पर फेंक दिया जा सकता है।)
persist()
शिकायत नहीं करेंगे कि उसके पास एक आईडी है, यह केवल तभी शिकायत करता है जब उसी आईडी के साथ कुछ पहले से ही डेटाबेस में है।
आप यहाँ सलाह के लिए आ सकते हैं कि कब प्रयोग करना है और कब मर्ज का उपयोग करना है । मुझे लगता है कि यह स्थिति पर निर्भर करता है: यह कैसे संभव है कि आपको एक नया रिकॉर्ड बनाने की आवश्यकता है और यह निरंतर डेटा को पुनर्प्राप्त करने के लिए कितना कठिन है।
चलो मान लें कि आप एक प्राकृतिक कुंजी / पहचानकर्ता का उपयोग कर सकते हैं।
डेटा को बनाए रखने की आवश्यकता होती है, लेकिन एक समय में एक रिकॉर्ड मौजूद होता है और एक अपडेट के लिए कॉल किया जाता है। इस मामले में आप एक दृढ़ता की कोशिश कर सकते हैं और अगर यह एक EntityExistsException फेंकता है, तो आप इसे देखते हैं और डेटा को संयोजित करते हैं:
प्रयास करें {unitManager.persist (निकाय)}
पकड़ (EntityExistsException अपवाद) {/ * पुनर्प्राप्त और मर्ज * /}
स्थायी डेटा को अपडेट करने की आवश्यकता है, लेकिन एक बार में डेटा के लिए अभी तक कोई रिकॉर्ड नहीं है। इस मामले में आप इसे देखते हैं, और अगर कंपनी गायब है तो एक दृढ़ता से काम करें:
एंटिटी = unitManager.find (की);
if (एंटिटी == null) {unitManager.persist (एंटिटी); }
और {/ * मर्ज * /}
यदि आपके पास प्राकृतिक कुंजी / पहचानकर्ता नहीं है, तो आपके पास यह पता लगाने का कठिन समय होगा कि इकाई मौजूद है या नहीं, या इसे कैसे देखना है।
मर्जों से दो तरीकों से निपटा जा सकता है:
persist (इकाई) का उपयोग पूरी तरह से नई संस्थाओं के साथ किया जाना चाहिए, उन्हें DB में जोड़ने के लिए (यदि इकाई पहले से ही DB में मौजूद है तो EntityExistsException throw होगा)।
मर्ज (निकाय) का उपयोग किया जाना चाहिए, यदि इकाई को अलग कर दिया गया था और बदल दिया गया था, तो दृढ़ता के संदर्भ में इकाई को वापस रखा जाए।
संभवतः दृढ़ता से INSERT sql स्टेटमेंट जेनरेट कर रहा है और UPDATE sql स्टेटमेंट को मर्ज कर रहा है (लेकिन मुझे यकीन नहीं है)।