2010-03-22 16 views
6

मैं हाइबरनेट/HQL सीखने की प्रक्रिया में अब भी कर रहा हूँ और मैं एक सवाल आधा सर्वोत्तम प्रथाओं प्रश्न/आधा मानसिक स्वास्थ्य की जांच है कि है।हाइबरनेट स्तंभ विशिष्टता सवाल

चलो कहते हैं कि मैं एक वर्ग एक करते हैं:

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

    @Column(unique=true) 
    private String name = ""; 

    //getters, setters, etc. omitted for brevity 
} 

मैं लागू करने के लिए है कि एक सहेजा जाता है कि के प्रत्येक उदाहरण के लिए विशिष्ट नाम (इसलिए @Column एनोटेशन) है चाहता हूँ, लेकिन मैं भी सक्षम होना चाहते हैं उस मामले को संभालने के लिए जहां पहले से ही एक उदाहरण सहेजा गया है जिसमें वह नाम है। मुझे ऐसा करने के दो तरीके दिखाई देते हैं:

1) मैं org.hibernate.exception.ConstraintViolationException को पकड़ सकता हूं जिसे session.saveOrUpdate() कॉल के दौरान फेंक दिया जा सकता है और इसे संभालने का प्रयास करें।

2) मैं मौजूदा एक के उदाहरण कि पहले से ही डीएओ में उस नाम है session.saveOrUpdate कॉल करने से पहले के लिए क्वेरी कर सकते हैं()।

अभी मैं दृष्टिकोण 2 की ओर झुका रहा हूं, क्योंकि दृष्टिकोण 1 में मुझे नहीं पता कि प्रोग्रामिंग के तरीके को किस प्रकार बाधा का उल्लंघन किया गया था (ए में कुछ अन्य अद्वितीय सदस्य हैं)। अभी मेरी DAO.save() कोड मोटे तौर पर इस तरह दिखता है:

public void save(A a) throws DataAccessException, NonUniqueNameException 
{ 
    Session session = sessionFactory.getCurrentSession(); 

    try 
    { 
     session.beginTransaction(); 

     Query query = null; 

     //if id isn't null, make sure we don't count this object as a duplicate 
     if(obj.getId() == null) 
     { 
      query = session.createQuery("select count(a) from A a where a.name = :name").setParameter("name", obj.getName()); 
     } 
     else 
     { 
      query = session.createQuery("select count(a) from A a where a.name = :name " + 
       "and a.id != :id").setParameter("name", obj.getName()).setParameter("name", obj.getName()); 
     } 

     Long numNameDuplicates = (Long)query.uniqueResult(); 
     if(numNameDuplicates > 0) 
      throw new NonUniqueNameException(); 

     session.saveOrUpdate(a); 
     session.getTransaction().commit(); 
    } 
    catch(RuntimeException e) 
    { 
      session.getTransaction().rollback(); 
      throw new DataAccessException(e); //my own class 
    } 
} 

मैं सही तरीके से इस बारे में जा रहा हूँ? मुझे प्रोग्राम के रूप में बता (अर्थात एक त्रुटि स्ट्रिंग के रूप में नहीं) जो मूल्य विशिष्टता बाधा उल्लंघन कर रहा है हाइबरनेट कर सकते हैं? क्वेरी को प्रतिबद्ध से अलग करके, क्या मैं थ्रेड-सुरक्षा त्रुटियों को आमंत्रित कर रहा हूं, या क्या मैं सुरक्षित हूं? यह आमतौर पर कैसे किया जाता है?

धन्यवाद!

उत्तर

3

मुझे लगता है कि अपने दूसरे दृष्टिकोण सबसे अच्छा है।

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

भले ही आप परीक्षण करेंगे यदि प्रत्येक बचत कार्रवाई पर तालिका में नाम पहले से मौजूद है, तो यह अभी भी प्रत्येक सम्मिलन के बाद फ्लशिंग से तेज़ होगा। (आप पुष्टि करने के लिए हमेशा बेंचमार्क कर सकते हैं।)

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

+0

क्या मेरे पास दूसरे दृष्टिकोण के साथ कोई थ्रेड सुरक्षा समस्या होगी? जहां तक ​​मैं समझता हूं, एसीआईडी ​​डीबी सिद्धांतों का "अलगाव" हिस्सा मुझे यहां मदद करने के लिए माना जाता है, लेकिन मुझे यकीन नहीं है कि इसके साथ कितना अनुपालन हाइबरनेट/hsqldb है। – Seth

+0

मुझे समझ में नहीं आता कि इस मामले के लिए अलगाव क्यों महत्वपूर्ण है। परीक्षण करना यदि एक नाम मौजूद है तो एक ही लेनदेन में होता है और डेटाबेस में डेटा की स्थिति में परिवर्तन नहीं करता है। – Rachel

1

दृष्टिकोण 1 ठीक हो सकता है अगर:

  • वहाँ इकाई में केवल एक बाधा है।
  • सिर्फ एक ही सत्र में गंदा वस्तु है।

याद रखें कि ऑब्जेक्ट को सहेजा नहीं जा सकता है जब तक flush() कहा जाता है या लेनदेन किया जाता है।

सबसे अच्छा त्रुटि के लिए मैं रिपोर्टिंग होगा: हर बाधा उल्लंघन के लिए

  1. उपयोग दृष्टिकोण दो, तो मैं उनमें से प्रत्येक के लिए एक विशिष्ट त्रुटि दे सकते हैं ..
  2. एक इंटरसेप्टर को लागू है कि एक बाधा के मामले में अपवाद लेनदेन (अधिकतम संख्या) को फिर से लेता है ताकि उल्लंघनों को किसी एक परीक्षण में पकड़ा नहीं जा सके। लेनदेन अलगाव स्तर के आधार पर यह केवल आवश्यक है।
संबंधित मुद्दे