2010-04-03 13 views
83

जेपीए में @Version एनोटेशन काम कैसे करता है?जावा - जेपीए - @ वर्जन एनोटेशन

जेपीए ही डेटासंग्रह रिकॉर्ड करने के लिए समवर्ती संशोधनों का पता लगाने के लिए अपने संस्थाओं में एक संस्करण क्षेत्र का उपयोग करता:

मैं विभिन्न जवाब जिसका निकालने इस प्रकार है के रूप में पाया। जब जेपीए रनटाइम एक ही रिकॉर्ड को समवर्ती रूप से संशोधित करने के प्रयास का पता लगाता है, तो यह लेनदेन के लिए अंतिम अपवाद करने का प्रयास अपवाद करता है।

लेकिन मुझे अभी भी यह सुनिश्चित नहीं है कि यह कैसे काम करता है।


इसके अलावा निम्नलिखित लाइनों से के रूप में:

आप संस्करण क्षेत्रों अपरिवर्तनीय विचार करना चाहिए। फ़ील्ड मान को बदलने से अपरिभाषित परिणाम हैं।

क्या इसका मतलब यह है कि हमें अपना संस्करण फ़ील्ड final के रूप में घोषित करना चाहिए?

+0

सभी यह होता है चेक/हर अद्यतन क्वेरी में संस्करण को अद्यतन है: 'अद्यतन myentity सेट MyColumn = 'नया मान', संस्करण = संस्करण +1 कहां संस्करण = [old.version]'। अगर किसी ने रिकॉर्ड अपडेट किया है, तो 'old.version' अब डीबी में से किसी एक से मेल नहीं खाएगा और जहां क्लॉज अपडेट होने से रोकेगा। 'अपडेट की गई पंक्ति' '0' होगी, जो जेपीए यह निष्कर्ष निकालने के लिए पता लगा सकता है कि एक समवर्ती संशोधन हुआ। –

उत्तर

145

लेकिन फिर भी मुझे यकीन नहीं है कि यह कैसे काम करता है?

मान लीजिए कि एक इकाई MyEntity व्याख्या किए गए version संपत्ति है दो:

@Entity 
public class MyEntity implements Serializable {  

    @Id 
    @GeneratedValue 
    private Long id; 

    private String name; 

    @Version 
    private Long version; 

    //... 
} 

अद्यतन पर, क्षेत्र @Version साथ एनोटेट वृद्धि की जाएगी और, कुछ इस तरह WHERE खंड को जोड़ा गया:

UPDATE MYENTITY SET ..., VERSION = VERSION + 1 WHERE ((ID = ?) AND (VERSION = ?)) 

यदि WHERE खंड रिकॉर्ड से मेल खाने में विफल रहता है (क्योंकि उसी इकाई को पहले ही अपडेट कर दिया गया है एक और धागा), तो दृढ़ता प्रदाता OptimisticLockException फेंक देगा।

यह मतलब यह है कि हम के रूप में अंतिम

कोई हमारे संस्करण क्षेत्र घोषित करना चाहिए, लेकिन आप सेटर संरक्षित के रूप में आप इसे कहते नहीं करना पड़ेगा बनाने पर विचार कर सकता है।

+5

मुझे कोड के इस टुकड़े के साथ एक नल-पॉइंटर अपवाद मिला, क्योंकि लंबे समय तक प्रारंभिक रूप से प्रारंभिक रूप से 0L के साथ स्पष्ट रूप से प्रारंभ किया जाना चाहिए। – Markus

+1

इसे 'लंबे समय तक ऑटो-अनबॉक्सिंग पर भरोसा न करें या केवल' longValue() 'पर कॉल न करें। आपको स्पष्ट 'शून्य' चेक की आवश्यकता है। स्पष्ट रूप से इसे स्वयं शुरू करना मैं ऐसा नहीं करूंगा क्योंकि इस क्षेत्र को ओआरएम प्रदाता द्वारा प्रबंधित किया जाना चाहिए। मुझे लगता है कि यह डीबी में पहले डालने पर '0L' पर सेट हो जाता है, इसलिए यदि यह 'शून्य' पर सेट है तो यह आपको बताता है कि यह रिकॉर्ड अभी तक जारी नहीं रहा है। –

+0

क्या यह एक इकाई को बनाने की कोशिश की जा रही है (कोशिश की गई) एक से अधिक बार बनाई गई है? मेरा मतलब है कि एक जेएमएस विषय संदेश किसी इकाई के निर्माण को ट्रिगर करता है और संदेश के कई उदाहरण संदेश सुनते हैं। मैं सिर्फ अद्वितीय बाधा उल्लंघन त्रुटि से बचना चाहता हूं .. – Manu

8

हर बार डेटाबेस में एक इकाई को अद्यतन किया जाता है, संस्करण फ़ील्ड को एक से बढ़ाया जाएगा। प्रत्येक ऑपरेशन जो डेटाबेस में इकाई को अद्यतन करता है, ने अपनी क्वेरी में WHERE version = VERSION_THAT_WAS_LOADED_FROM_DATABASE जोड़ दिया होगा।

आपके ऑपरेशन की प्रभावित पंक्तियों की जांच में जेपीए फ्रेमवर्क यह सुनिश्चित कर सकता है कि लोडिंग और अपनी इकाई को बनाए रखने के बीच कोई समवर्ती संशोधन नहीं था क्योंकि क्वेरी को डेटाबेस में आपकी इकाई नहीं मिलती है जब लोड और जारी रखने के बीच संस्करण संख्या बढ़ जाती है ।

+0

JPAUpdateQuery के माध्यम से नहीं है यह नहीं है। तो "डेटाबेस में इकाई को अद्यतन करने वाले प्रत्येक ऑपरेशन में WHERE संस्करण = VERSION_THAT_WAS_LOADED_FROM_DATABASE को अपनी क्वेरी में जोड़ दिया जाएगा" सत्य नहीं है। –

1

संस्करण यह सुनिश्चित करने के लिए उपयोग किया जाता है कि एक समय में केवल एक ही अपडेट। जेपीए प्रदाता संस्करण की जांच करेगा, यदि अपेक्षित संस्करण पहले से बढ़ता है तो कोई और पहले से ही इकाई को अपडेट कर देगा ताकि एक अपवाद फेंक दिया जा सके।

इसलिए इकाई मूल्य अपडेट करना अधिक सुरक्षित, अधिक आशावादी होगा।

यदि मूल्य लगातार बदलता है, तो आप संस्करण फ़ील्ड का उपयोग न करने पर विचार कर सकते हैं। एक उदाहरण के लिए "एक इकाई काउंटर क्षेत्र है, कि इच्छा हर वृद्धि हुई पहुँचा एक वेब पेज"

15

हालांकि @Pascal जवाब पूरी तरह से वैध है, मेरे अनुभव से मैं आशावादी ताला पूरा करने के लिए उपयोगी नीचे कोड पाते हैं:

@Entity 
public class MyEntity implements Serializable {  
    // ... 

    @Version 
    @Column(name = "optlock", columnDefinition = "integer DEFAULT 0", nullable = false) 
    private long version = 0L; 

    // ... 
} 

क्यों? क्योंकि:

  1. आशावादी ताला लगा काम नहीं करेगा अगर @Version साथ एनोटेट क्षेत्र गलती से null को तैयार है।
  2. चूंकि यह विशेष फ़ील्ड किसी भ्रामक से बचने के लिए वस्तु का व्यावसायिक संस्करण आवश्यक नहीं है, इसलिए version की बजाय optlock जैसे इस क्षेत्र को नाम देना पसंद करते हैं।

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

+0

मैं इसे ** 'u_lmod' ** (उपयोगकर्ता अंतिम बार संशोधित) कहता हूं ** ** उपयोगकर्ता मानव या परिभाषित (स्वचालित) प्रक्रिया/इकाई/ऐप ** हो सकता है (इसलिए अतिरिक्त रूप से भंडारण 'u_lmod_id' भी समझ में आ सकता है)। (यह मेरे विचार में एक बहुत ही बुनियादी व्यापार-मेटा-विशेषता है)। यह आम तौर पर DATE (TIME) के रूप में अपना मूल्य संग्रहीत कर रहा है (जिसका मतलब साल के बारे में जानकारी है ...मिलिस) यूटीसी में (यदि टाइमज़ोन के साथ संपादक का टाइमज़ोन "स्थान" स्टोर करना महत्वपूर्ण है)। डीडब्ल्यूएच सिंक परिदृश्य के लिए अतिरिक्त रूप से बहुत उपयोगी है। –

+4

मुझे लगता है कि एक पूर्ण जावा के मिलान के लिए डीबी प्रकार में एक पूर्णांक के बजाय बिगिन का उपयोग किया जाना चाहिए। – Dmitry

+0

अच्छा बिंदु दिमित्री, धन्यवाद, हालांकि जब यह IMHO संस्करण संस्करण की बात आती है तो यह वास्तव में कोई फर्क नहीं पड़ता। –

0

बस थोड़ा और जानकारी जोड़ना।

जेपीए आपके लिए हुड के तहत संस्करण का प्रबंधन करता है, हालांकि ऐसा नहीं होता है जब आप JPAUpdateClause() के माध्यम से अपना रिकॉर्ड अपडेट करते हैं, तो आपको क्वेरी में संस्करण वृद्धि को मैन्युअल रूप से जोड़ना होगा।

पेड्रो

+1

'JPAUpdateClause' क्या है? –

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