2010-05-18 12 views
13

को अद्यतन करने के नए रिकॉर्ड बनाता है मैं एक वर्ग उपयोगकर्ताहाइबरनेट में saveOrUpdate() का उपयोग करने के बजाय मौजूदा

class User { 
    int id; 
    String name; 
} 

जहां id देशी जनरेटर है User.hbm.xml और name में डीबी में प्राथमिक कुंजी है।

मेरे डेटाबेस में मैंने उपयोगकर्ताओं के बारे में कुछ जानकारी सहेजी।

मैं उपयोगकर्ता के बारे में इस जानकारी से कनेक्ट करना चाहता हूं।

मेरी DB में उदाहरण के लिए मैं एक पंक्ति है INSERT INTO User VALUES ('Bill');

Main.java

User bill = new User(); 
bill.setName("Bill"); 
session.saveOrUpdate(bill); 

इस कोड को हमेशा तालिका में एक नया Bill पंक्ति सम्मिलित करने के बजाय मौजूदा Bill पंक्ति को अद्यतन करने की कोशिश करता है।

उत्तर

1

तो, आईडी डेटाबेस में सहेजा नहीं गया है?

आईडी डीबी में प्राथमिक कुंजी क्यों नहीं है, यदि आप इसे हाइबरनेट में पहचानकर्ता के रूप में मानचित्रित करते हैं?

आपने डेटाबेस में 'नाम' पर एक अनन्य बाधा क्यों नहीं डाली है, और आईडी पर प्राथमिक कुंजी बाधा उत्पन्न नहीं की है?

+0

आपके भरोसेमंद के लिए Thx। 'id' प्राथमिक कुंजी है और 'नाम' में अद्वितीय constriant हमारे पास ऑब्जेक्ट क्लास उपयोगकर्ता है उदाहरण के लिए: ' उपयोगकर्ता बिल = नया उपयोगकर्ता() 'और बिल के बारे में विशेषताएँ जो हम कीबार्ड या वेबसाइट से प्राप्त करते हैं, और मेरा प्रश्न है : आप saveOrUpdate() का अर्थ कैसे बना सकते हैं यदि बिल.नाम डीबी में मौजूद है तो हम अपडेट कहते हैं() अन्यथा हम बिल को सहेजते हैं। – kunkanwan

-1

आप session.update (वस्तु), जबकि आप अद्यतन कर रहे हैं, और session.save (वस्तु) का उपयोग करना चाहिए, जबकि आप

+3

और 'saveOrUpdate()' आपके लिए यह कर सकता है, जो इस विधि का बिंदु है ... –

+0

हाँ, आप सही हैं, लेकिन मैं चाहता हूं कि हाइबरनेट से फ़ंक्शन सेवऑरअपडेट() मेरे लिए काम करे। मैं अपना saveOrUpdate() लिख सकता हूं, जहां मैं डीबी में 'name' मौजूद है और कॉल सेव() या अपडेट() को चुनने में चयन करता हूं। मुझे लगता है कि यह अच्छा विचार नहीं है, और शायद हाइबरनेट के पास बेहतर समाधान है उदाहरण के लिए बराबर ओवरराइड() जहां हम bussines कुंजी से तत्व की तुलना करते हैं। – kunkanwan

27

इस कोड को बचत कर रहे हैं हमेशा डेटाबेस के लिए डालने बिल की कोशिश कर रहा है, बल्कि अद्यतन जब से बिल के बारे में पंक्ति डीबी में मौजूद है ...

हाइबरनेट कोर प्रलेखन की धारा 10.7. Automatic state detection से:

saveOrUpdate() निम्नलिखित है:

  • अगर वस्तु इस सत्र में पहले से ही लगातार है, ऐसा कुछ भी नहीं
  • अगर सत्र से जुड़े एक अन्य ऑब्जेक्ट में एक ही पहचानकर्ता है, पूर्व में फेंक दें धारणा
  • अगर वस्तु नहीं पहचानकर्ता संपत्ति, save() यह
  • वस्तु के पहचानकर्ता एक नव instantiated वस्तु को सौंपा मूल्य अधिक हो, तो save() यह
  • अगर वस्तु एक <version> द्वारा संस्करणीकृत जाता है या <timestamp>, और संस्करण संपत्ति मान एक ही मान एक नए तत्काल ऑब्जेक्ट को सौंपा गया है, save() यह
  • अन्यथा update() वस्तु

जब आप ऐसा करेंगे:

User bill = new User(); 
bill.setName("Bill"); 
session.saveOrUpdate(bill); 

इस नव निर्मित उदाहरण किसी भी पहचानकर्ता मूल्य सौंपा नहीं है और saveOrUpdate() यह save() जाएगा, के रूप में दस्तावेज। यदि यह वही नहीं है जो आप चाहते हैं, तो name प्राथमिक कुंजी बनाएं।

+0

आपके भरोसेमंद के लिए Thx, मैं देखता हूं कि क्यों मेरा प्रोग्राम हमेशा डालने का प्रयास करता है। मैं प्राथमिक कुंजी नाम के बिना ऐसा कैसे कर सकता हूं क्योंकि मेरे पास आईडी है जो तेज़ और आसान है। मैं इसे अतिरिक्त चयन का उपयोग करके कर सकता हूं: 'उपयोगकर्ता बिल = नया उपयोगकर्ता(); bill.setName ("बिल"); bill.setId (func()); 'जहां func() एक फ़ंक्शन है जिसके परिणामस्वरूप शून्य होता है जब 'name =' bill'' के साथ पंक्ति मौजूद नहीं होती है अन्यथा इस पंक्ति को आईडी नंबर लौटाएं; चयन के बिना मैं यह कैसे कर सकता हूं? प्रो डेवलपर इस समस्या को कैसे हल करें? – kunkanwan

+0

@ कंकानवान: मुझे यकीन नहीं है कि मुझे इस "प्रो डेवलपर" को कैसे समझना चाहिए। अभी, यह आपको आगे की मदद करने के लिए प्रेरित नहीं करता है। –

+0

मुझे डर है कि आप मुझे समझ में नहीं आते हैं। मेरी अंग्रेजी खराब है। वाक्य 'प्रो डेवलपर' में मैं जानता हूं कि सॉफ्टवेयर उद्योग में यह कैसे हल करें (मैं अनुभव के बिना छात्र हूं) जहां अतिरिक्त चयन के साथ मेरा सरल कार्य पर्याप्त नहीं है। अगर तुमको चोट पहुंची हो तो मुझे खेद है। – kunkanwan

14

तो आप चाहते हैं:

User u1 = new User("Bill"); 
session.save(u1); 
User u2 = new User("Bill"); 
session.saveOrUpdate(u2); 

कि U1 और U2 सूचना के लिए एक ही बिल रहे हैं और केवल एक बार की दुकान? हाइबरनेट को यह जानने का कोई तरीका नहीं है कि बिल एक ही व्यक्ति हैं। यह केवल यूजर यू 2 की आईडी को देखता है, यह देखता है कि यह सेट नहीं है, निष्कर्ष निकाला है कि यू 2 डाला जाना चाहिए, कोशिश करता है और अपवाद की रिपोर्ट करता है।

SaveOrUpdate वर्तमान में सत्र से जुड़ा हुआ एक पूरी तरह से नई वस्तु और एक लोड ऑब्जेक्ट दोनों बनी हुई है। तो यह काम करता है (यह मानते हुए कि आप एक findByName विधि कहीं और वहाँ एक और विशेषता है, के favoriteColor मान लीजिए):

User u1 = new User("Bill"); 
u1.setFavoriteColor("blue"); 
session.saveOrUpdate(u1); 
User u2 = findByName("Joe"); 
u2.setFavoriteColor("red"); 
session.saveOrUpdate(u2); 

लेकिन है कि आप क्या चाहते हैं, सही नहीं है?

आपकी समस्या एक सरोगेट प्राथमिक कुंजी और अलग से, एक व्यापार कुंजी (एक विशिष्टता बाधा के माध्यम से लागू) होने के कारण आपकी इकाई से भी बदतर हो गई है। आप एक आईडी क्षेत्र आपके पास नहीं था और केवल प्राथमिक कुंजी के रूप नाम, आप (मर्ज बनाम saveOrUpdate की चर्चा के लिए, look here) मर्ज() इस्तेमाल कर सकते हैं:

User u1 = new User("Bill"); 
u1.setFavoriteColor("blue"); 
session.save(u1); 
User u2 = new User("Bill"); 
u2.setFavoriteColor("red"); 
u2 = session.merge(u2); 

लेकिन आपको लगता है कि नहीं है, आप आईडी पर पीके बाधा और नाम पर विशिष्टता दोनों को लागू करने की आवश्यकता है। तो आपको विलय के कुछ बदलाव की आवश्यकता होगी जो ऐसा करता है।

public User mergeByName(User user) { 
    User merged; 
    User candidate = findByName(user.getName()); 
    if (candidate != null) { 
     user.setId(candidate.getId()); 
     merged = session.merge(user); 
    } else { 
     session.save(user); 
     merged = user; 
    } 
    return merged; 
} 
1

पहला सवाल:: बहुत मोटे तौर पर, आप इन पंक्तियों के साथ कुछ करना चाहते हैं तो आप "बिल" नामक उपयोगकर्ता लाने के लिए की जरूरत है। आप वह कैसे करेंगें? यह आपको एक विचार देना चाहिए।

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

Query query = session.createQuery("update User u set u.name = :newName where u.name=:name"); 
query.setString("name", "Bill"); 
query.setString("newName", "John"); 
query.executeUpdate(); 
-3

यदि नाम फ़ील्ड प्राथमिक कुंजी है। फिर यदि आप एक ही नाम को एक से अधिक बार सेट करते हैं, तो यह नया रिकॉर्ड कैसे बनाएगा। हो सकता है कि आप अवधारणा को सही नहीं समझ रहे हों।

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