synchronized
जावा कीवर्ड कैसे काम करता है
जब आप जोड़ते हैं synchronized
कीवर्ड को स्टैटिक विधि से , तो विधि को एक बार में केवल एक थ्रेड द्वारा बुलाया जा सकता है।
आपके मामले में, हर विधि कॉल करेगी:
- कोई नया बनाएं
SessionFactory
- कोई नया बनाएं
Session
- इकाई लाना
- कॉलर को इकाई वापस लौटाएं
हालाँकि, ये आपकी आवश्यकताएं थीं:
- मैं चाहता हूँ कि यह एक ही DB उदाहरण के लिए जानकारी तक पहुँच को रोकने के लिए है।
- रोकने
getObjectById
जब यह एक विशेष वर्ग से पुकारा जाता है सभी वर्गों के लिए बुलाया जा रहा है
इसलिए, भले ही getObjectById
विधि थ्रेड-सुरक्षित हो, कार्यान्वयन गलत है।
SessionFactory
सर्वोत्तम प्रथाएं
यह SessionFactory
थ्रेड-सुरक्षित है, और इसे बनाने के लिए एक बहुत महंगी वस्तु है क्योंकि इसमें इकाई वर्गों को पार्स करने और आंतरिक इकाई मेटामोडियम प्रतिनिधित्व का निर्माण करने की आवश्यकता है।
इसलिए, आपको SessionFactory
हर getObjectById
विधि कॉल पर नहीं बनाना चाहिए ।
इसके बजाय, आपको इसके लिए एक एकल उदाहरण बनाना चाहिए।
private static final SessionFactory sessionFactory = new Configuration()
.configure()
.buildSessionFactory();
Session
हमेशा बंद किया जाना चाहिए
आप बंद नहीं किया Session
एक में finally
ब्लॉक, और इस डाटाबेस संसाधन लीक कर सकते हैं अगर एक अपवाद जब इकाई लोड हो रहा है फेंक दिया है।
Session.load
JavaDoc एक HibernateException
इकाई में डेटाबेस में नहीं पाया जा सकता है, तो विधि के अनुसार ।
यदि उदाहरण मौजूद है ( get()
इसके बजाय उपयोग ) यह निर्धारित करने के लिए आपको इस विधि का उपयोग नहीं करना चाहिए । इसका उपयोग केवल उस उदाहरण को प्राप्त करने के लिए करें जिसे आप मानते हैं कि मौजूद है, जहां गैर-अस्तित्व एक वास्तविक त्रुटि होगी।
इसलिए आपको इस तरह से इसे finally
बंद करने के लिए एक ब्लॉक का उपयोग करने की आवश्यकता है Session
:
public static synchronized Object getObjectById (Class objclass, Long id) {
Session session = null;
try {
session = sessionFactory.openSession();
return session.load(objclass, id);
} finally {
if(session != null) {
session.close();
}
}
}
बहु-धागा पहुंच को रोकना
आपके मामले में, आप यह सुनिश्चित करना चाहते थे कि केवल एक धागा उस विशेष इकाई तक पहुंच प्राप्त करे।
लेकिन synchronized
कीवर्ड केवल दो थ्रेड को कॉल करने से रोकता हैgetObjectById
समवर्ती है। यदि दो धागे एक के बाद एक इस विधि को कहते हैं, तो आपके पास इस इकाई का उपयोग करने वाले दो धागे होंगे।
इसलिए, यदि आप किसी दिए गए डेटाबेस ऑब्जेक्ट को लॉक करना चाहते हैं तो कोई अन्य धागा इसे संशोधित नहीं कर सकता है, तो आपको डेटाबेस लॉक का उपयोग करने की आवश्यकता है।
synchronized
कीवर्ड केवल एक JVM में काम करता है। यदि आपके पास कई वेब नोड्स हैं, तो यह मल्टीपल जेवीएम के मल्टी-थ्रेड एक्सेस को नहीं रोक पाएगा।
DB को परिवर्तनों को लागू करते समय आपको क्या करने की आवश्यकता है, इसका उपयोग करें LockModeType.PESSIMISTIC_READ
याLockModeType.PESSIMISTIC_WRITE
इस तरह करें:
Session session = null;
EntityTransaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.getTransaction();
tx.begin();
Post post = session.find(
Post.class,
id,
LockModeType.LockModeType.PESSIMISTIC_READ
);
post.setTitle("High-Performance Java Perisstence");
tx.commit();
} catch(Exception e) {
LOGGER.error("Post entity could not be changed", e);
if(tx != null) {
tx.rollback();
}
} finally {
if(session != null) {
session.close();
}
}
तो यही वह है जो मैंने किया:
- मैंने एक नया बनाया
EntityTransaction
और एक नया डेटाबेस लेनदेन शुरू किया
- मैंने
Post
संबद्ध डेटाबेस रिकॉर्ड पर ताला लगाते हुए इकाई को लोड किया
- मैंने बदल दिया
Post
इकाई को और लेनदेन को प्रतिबद्ध किया
Exception
फेंके जाने की स्थिति में , मैंने लेन-देन वापस कर दिया
एसीआईडी और डेटाबेस लेनदेन के बारे में अधिक जानकारी के लिए, इस लेख को भी देखें।