2010-09-13 9 views
10

तक पहुंचने के लिए फोर्स हाइबरनेट क्वेरी को मैंने अपने लेनदेन में एक इकाई लोड की है और उस इकाई की संपत्ति बदल दी है। लेनदेन अभी तक नहीं किया गया है। अब मैं बदली हुई संपत्ति का मूल मूल्य प्राप्त करना चाहता हूं।डेटाबेस

मैंने लेनदेन में लोड की गई इकाई की आईडी के साथ select p.property from Person p where p.id = 1 जैसे एचक्यूएल क्वेरी के साथ प्रयास किया है।

मैंने क्वेरी निष्पादित करने से पहले query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); सेट किया है। लेकिन कोई सफलता नहीं। हाइबरनेट वर्तमान लेनदेन में सेट के रूप में मान देता है, डेटाबेस से नहीं।

क्या इसके आसपास कोई रास्ता है?

+0

क्या आप उस समस्या से समाप्त नहीं होते हैं जहां हाइबरनेट दो बार सत्र में एक ही इकाई के बारे में शिकायत करता है? लगता है जैसे आप शायद कार्यान्वयन पर फिर से विचार करना चाहें। –

उत्तर

11

मैंने अपने लेनदेन में एक इकाई लोड की है और उस इकाई की संपत्ति बदल दी है। लेनदेन अभी तक नहीं किया गया है। अब मैं बदली हुई संपत्ति का मूल मूल्य प्राप्त करना चाहता हूं।

संक्षेप में: पुराने मूल्य को ट्रैक करें।

मैंने एक एचक्यूएल क्वेरी के साथ प्रयास किया है जैसे कि व्यक्ति पी से चुनिंदा पी.प्रोपर्टी, जहां लेनदेन में लोड की गई इकाई की आईडी के साथ p.id = 1।

हाइबरनेट किसी दिए गए डेटाबेस पहचानकर्ता के लिए सत्र (प्रथम स्तर कैश) में किसी इकाई का एक अद्वितीय संस्करण लोड करता है। यह काम नहीं करेगा।

मैंने query.setHint ("org.hibernate.cacheMode", CacheMode.IGNORE) सेट किया है; क्वेरी निष्पादित करने से पहले।

यह संकेत क्वेरी कैश (कि दूसरे स्तर-कैश पर भरोसा करते हैं), यह आपके वर्तमान "मुद्दा" को प्रभावित नहीं करेगा प्रभावित करने के लिए प्रयोग किया जाता है।

क्या इसके आसपास कोई रास्ता है?

या तो

  • उपयोग session.refresh() अपने इकाई का एक बार पुनः लोड करने के लिए मजबूर करने के लिए (और आप परिवर्तनों को ढीला होगा)
  • दुकान पिछले मान शुरू में उल्लेख किया।
  • एक ऐसी सेवा का आह्वान करता है जो किसी अन्य लेनदेन में क्वेरी करता है।
2

यह आपकी मदद कर सकते हैं:

आप क्वेरी कैश मजबूर करने के लिए अपने क्षेत्रों में से एक (किसी भी कैश्ड परिणाम यह वहाँ पाता उपेक्षा) ताज़ा करने के लिए चाहते हैं तो आप org.hibernate.Query उपयोग कर सकते हैं .setCacheMode (CacheMode.REFRESH)। इस क्षेत्र के संयोजन के साथ आप दिए गए प्रश्न के लिए परिभाषित किया गया है, हाइबरनेट को उस विशेष क्षेत्र में रीफ्रेश किए जाने के लिए चुनिंदा रूप से लागू करेगा। यह मामलों में जहां अंतर्निहित डेटा एक अलग प्रक्रिया के माध्यम से अद्यतन किया गया है हो सकता है में विशेष रूप से उपयोगी है और एक बहुत ही अधिक कुशल org.hibernate.SessionFactory.evictQueries के माध्यम से क्षेत्र के थोक बेदखली के लिए वैकल्पिक है()।

(http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html से, खंड 20.4.2)।

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

+0

मेरे उत्तर की समीक्षा में मुझे लगता है कि यह आपकी समस्या को पूरी तरह से संबोधित नहीं करता है। भले ही आप दूसरे स्तर के कैश को पूरी तरह अक्षम कर दें, फिर भी आपका इकाई डेटा पहले स्तर के कैश (सत्र) के लिए आ रहा है। इसके लिए, आपको ऑब्जेक्ट को रीफ्रेश या बेदखल करना चाहिए ... लेकिन फिर आपको उन फ़ील्ड को फिर से दर्ज करना चाहिए जिन्हें आप लेनदेन प्रतिबद्धता में सहेजना चाहते हैं। – Sebastian

1

ऐसा करने का एकमात्र तरीका क्वेरी के बाहर क्वेरी को चलाने के लिए होगा वर्तमान लेनदेन

7

स्टेटलेस सत्र ने मेरे लिए काम किया।

StatelessSession statelessSession = sessionFactory.openStatelessSession(); 
try { 
    return statelessSession.get(Ticket.class, ticketKey, LockMode.READ) 
} finally { 
    statelessSession.close() 
}