2013-08-13 8 views
12

मैं एक बहु थ्रेडेड एप्लिकेशन के लिए हाइबरनेट का उपयोग करने की कोशिश कर रहा हूं जिसमें प्रत्येक थ्रेड किसी ऑब्जेक्ट को पुनर्प्राप्त करता है और इसे किसी तालिका में डालने का प्रयास करता है। मेरा कोड नीचे जैसा दिखता है। मेरे पास प्रति थ्रेड स्थानीय हाइबरनेट सत्र ऑब्जेक्ट हैं और प्रत्येक InsertData में मैं शुरू करता हूं ट्रांज़ेक्शन और प्रतिबद्धता।एक बहु थ्रेडेड एप्लिकेशन में हाइबरनेट का उपयोग कैसे करें?

समस्या का सामना करना पड़ रहा है कि कई बार मैं मिलता है "org.hibernate.TransactionException: नेस्टेड लेनदेन समर्थित नहीं"

जब से मैं हाइबरनेट करने के लिए मैं नहीं जानता कि यदि मैं क्या कर रहा हूँ सही है या नया हूँ नहीं? कृपया मुझे बताएं कि बहु थ्रेडेड ऐप में हाइबरनेट का उपयोग करने के लिए सही तरीका क्या है और ऊपर उल्लिखित अपवाद से कैसे बचें।

धन्यवाद

public class Worker extends Thread { 
private Session session = null; 

Worker() { 
    SessionFactory sf = HibernateUtil.getSessionFactory(); // Singleton 
    session = sf.openSession(); 
    session.setFlushMode(FlushMode.ALWAYS); 
} 

public void run() { 
    // Some loop which will run thousand of times 
    for (....) 
    { 
     InsertData(b); 
    } 
    session.close(); 
} 

// BlogPost Table has (pk = id AutoGenerated), dateTime, blogdescription etc. 
private void InsertData(BlogPost b) { 
    session.beginTransaction(); 
    Long id = (Long) session.save(b); 
    b.setId(id); 
    session.getTransaction().commit(); 
} 
} 

मेरे हाइबरनेट कॉन्फ़िग फ़ाइल है c3p0.min_size=10 और c3p0.max_size=20

+0

क्या यह 'b.setId()' होना चाहिए? –

+0

हाँ, बस इसे ठीक किया गया। मेरे वास्तविक कोड का एक न्यूनतम उदाहरण बनाने की कोशिश करते समय टाइपो हुआ। – Rahul

उत्तर

10
सत्र-वस्तुओं-प्रति-धागा साथ

, जब तक आप एक से अधिक थ्रेड के बीच सत्र वस्तुओं साझा नहीं कर रहे, तब तक आप ठीक हो जाएगा ।

जो त्रुटि आप प्राप्त कर रहे हैं वह आपके बहुप्रचारित उपयोग या आपके सत्र प्रबंधन से संबंधित नहीं है। session.save() के साथ-साथ स्पष्ट रूप से आईडी सेट करने का आपका उपयोग बिल्कुल सही नहीं है।

BlogPost के लिए अपने मानचित्रण देखकर बिना अपनी हार्ड बताने के लिए, लेकिन अगर आप हाइबरनेट बता दिया है प्राथमिक कुंजी के रूप id क्षेत्र का उपयोग करने, और आप प्राथमिक कुंजी के लिए देशी जनरेटर का उपयोग कर रहे हैं, तुम सब करने की जरूरत है यह है :

session.beginTransaction(); 
session.persist(b); 
session.flush(); // only needed if flush mode is "manual" 
session.getTransaction().commit(); 

हाइबरनेट आप के लिए में आईडी भर जाएगा, persist() डालने लेन-देन की सीमा के भीतर होने की कारण होगा (save() लेनदेन के बारे में परवाह नहीं है)। यदि आपका फ्लश मोड मैन्युअल पर सेट नहीं है तो आपको flush() पर कॉल करने की आवश्यकता नहीं है क्योंकि Transaction.commit() आपके लिए इसे संभालेगा।

ध्यान दें कि persist() के साथ, ब्लॉगपोस्ट की आईडी को तब तक सेट करने की गारंटी नहीं है जब तक सत्र फ़्लश नहीं हो जाता है, जो आपके उपयोग के लिए ठीक है।

शान से त्रुटियों को संभाल करने के लिए:

try { 
    session.beginTransaction(); 
    try { 
     session.persist(b); 
     session.flush(); // only needed if flush mode is "manual" 
     session.getTransaction().commit(); 
    } catch (Exception x) { 
     session.getTransaction().rollback(); 
     // log the error 
    } 
} catch (Exception x) { 
    // log the error 
} 

वैसे, मैं BlogPost.setId() निजी, या पैकेज दृश्यमान बनाने का सुझाव दे। यह एक कार्यान्वयन त्रुटि की संभावना है यदि कोई अन्य वर्ग आईडी को स्पष्ट रूप से सेट करता है (फिर मूल जनरेटर मानता है, और प्राथमिक कुंजी के रूप में आईडी)।

+1

धन्यवाद जेसन, मेरे पास रोलबैक() नहीं था जिसके कारण पिछला अपवाद थ्रेड के लिए एक लेनदेन को खोल रहा था और बाद में शुरूआत ट्रांसलेशन का उपयोग "लेनदेन अपवाद" को फेंकने के लिए किया जाता था। – Rahul

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