इस लंबे उत्तर से डरो मत। यह विषय सरल नहीं है।
डिफ़ॉल्ट जेपीए तक लागू पढ़ें अगर आप किसी भी ताला (LockModeType.NONE
का उपयोग कर के रूप में ही व्यवहार) का उल्लेख नहीं करते अलगाव स्तर प्रतिबद्ध है।
पढ़ें प्रतिबद्धगैर अस्तित्व की आवश्यकता है गंदा की पढ़ घटना। टी 2 के बाद बस टी 1 केवल टी 2 द्वारा किए गए परिवर्तन देख सकता है।
जेपीए में आशावादी लॉकिंग का उपयोग अलगाव स्तर रीसेट करने योग्य पढ़ता है।
यदि टी 1 शुरुआत में और लेनदेन के अंत में कुछ डेटा पढ़ता है, दोहराया जाने योग्य पढ़ता है कि टी 1 उसी डेटा को देखता है भले ही टी 2 ने डेटा बदल दिया हो और टी 1 के बीच में किया गया हो।
और यहां मुश्किल हिस्सा आता है। जेपीए प्राप्त करता है रीसेट करने योग्य को सबसे आसान तरीके से पढ़ता है: को रोकना गैर-दोबारा पढ़ने योग्य घटना। जेपीए आपके पढ़ने के स्नैपशॉट्स को रखने के लिए पर्याप्त परिष्कृत नहीं है। यह केवल अपवाद को बढ़ाकर दूसरे पढ़ने को रोकता है (यदि डेटा पहले पढ़ने से बदल गया है)।
आप दो आशावादी लॉक विकल्पों में से चुन सकते हैं: (जेपीए 1.0 में LockModeType.WRITE
)
अंतर क्या है दोनों के बिच में?
मुझे इस Person
इकाई पर उदाहरणों के साथ उदाहरण दें।
@Entity
public class Person {
@Id int id;
@Version int version;
String name;
String label;
@OneToMany(mappedBy = "person", fetch = FetchType.EAGER)
List<Car> cars;
// getters & setters
}
अब हम एक व्यक्ति का नाम दिया है जॉन डेटाबेस में संग्रहीत मान लें। हम इस व्यक्ति को टी 1 में पढ़ते हैं लेकिन दूसरे लेनदेन टी 2 में अपना नाम माइक पर बदलते हैं।
किसी भी ताला लगा
Person person1 = em1.find(Person.class, id, LockModeType.NONE); //T1 reads Person("John")
Person person2 = em2.find(Person.class, id); //T2 reads Person("John")
person2.setName("Mike"); //Changing name to "Mike" within T2
em2.getTransaction().commit(); // T2 commits
System.out.println(em1.find(Person.class, id).getName()); // prints "John" - entity is already in Persistence cache
System.out.println(
em1.createQuery("SELECT count(p) From Person p where p.name='John'")
.getSingleResult()); // prints 0 - ups! don't know about any John (Non-repetable read)
आशावादी पढ़ने ताला बिना जब परिवर्तन अन्य संस्था (शायद एक गैर स्वामित्व संबंध) के लिए किया जाता
Person person1 = em1.find(Person.class, id, LockModeType.OPTIMISTIC); //T1 reads Person("John")
Person person2 = em2.find(Person.class, id); //T2 reads Person("John")
person2.setName("Mike"); //Changing name to "Mike" within T2
em2.getTransaction().commit(); // T2 commits
System.out.println(
em1.createQuery("SELECT count(p) From Person p where p.name='John'")
.getSingleResult()); // OptimisticLockException - The object [[email protected]] cannot be updated because it has changed or been deleted since it was last read.
LockModeType.OPTIMISTIC_FORCE_INCREMENT
प्रयोग किया जाता है और हम अखंडता को संरक्षित करना चाहते हैं। मुझे जॉन के साथ एक नई कार प्राप्त करने का उदाहरण दें। आशावादी पढ़ने ताला
Person john1 = em1.find(Person.class, id); //T1 reads Person("John")
Person john2 = em2.find(Person.class, id, LockModeType.OPTIMISTIC); //T2 reads Person("John")
//John gets a mercedes
Car mercedes = new Car();
mercedes.setPerson(john2);
em2.persist(mercedes);
john2.getCars().add(mercedes);
em2.getTransaction().commit(); // T2 commits
//T1 doesn't know about John's new car. john1 in stale state. We'll end up with wrong info about John.
if (john1.getCars().size() > 0) {
john1.setLabel("John has a car");
} else {
john1.setLabel("John doesn't have a car");
}
em1.flush();
आशावादी लिखने ताला
Person john1 = em1.find(Person.class, id); //T1 reads Person("John")
Person john2 = em2.find(Person.class, id, LockModeType.OPTIMISTIC_FORCE_INCREMENT); //T2 reads Person("John")
//John gets a mercedes
Car mercedes = new Car();
mercedes.setPerson(john2);
em2.persist(mercedes);
john2.getCars().add(mercedes);
em2.getTransaction().commit(); // T2 commits
//T1 doesn't know about John's new car. john1 in stale state. That's ok though because proper locking won't let us save wrong information about John.
if (john1.getCars().size() > 0) {
john1.setLabel("John has a car");
} else {
john1.setLabel("John doesn't have a car");
}
em1.flush(); // OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
हालांकि जेपीए कल्पना में एक निम्न टिप्पणी नहीं है, हाइबरनेट और EclipseLink अच्छी तरह से बर्ताव करता है और उसका उपयोग नहीं करते ।
संस्करणीकृत वस्तुओं के लिए, यह एक कार्यान्वयन LockMode- Type.OPTIMISTIC_FORCE_INCREMENT जहां LockModeType.OPTIMISTIC अनुरोध किया गया था, लेकिन इसके विपरीत नहीं का उपयोग करने के लिए स्वीकार्य है।
मुझे लगता है कि हम उस इकाई को अद्यतन करने के मामले में OPTIMISTIC_FORCE_INCREMENT का उपयोग करते हैं जिसमें फ़ील्ड के रूप में अन्य प्रकार की इकाइयां होती हैं (@oneToOne, @oneToMany)। इसलिए हम OPTIMISTIC_FORCE_INCREMENT के साथ लॉक करते हैं उदाहरण के लिए सभी ListItem जब हम सूची अपडेट करना चाहते हैं। इस प्रकार, जब हम यह सुनिश्चित करते हैं कि हम उस इकाई से जुड़े सभी संस्थाओं को अपरिवर्तित कर रहे हैं। यही है ना ? –