BAEL-1713: Pessimistic Locking in JPA

Tests for the article.
This commit is contained in:
Patryk Kucharz 2018-04-30 16:33:50 +02:00
parent 7140229ca0
commit c0c319b13f
18 changed files with 906 additions and 26 deletions

View File

@ -1,30 +1,12 @@
package com.baeldung.hibernate; package com.baeldung.hibernate;
import com.baeldung.hibernate.pojo.Employee; import com.baeldung.hibernate.pessimisticlocking.Individual;
import com.baeldung.hibernate.pojo.EntityDescription; import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingCourse;
import com.baeldung.hibernate.pojo.OrderEntry; import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingEmployee;
import com.baeldung.hibernate.pojo.OrderEntryIdClass; import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingStudent;
import com.baeldung.hibernate.pojo.OrderEntryPK; import com.baeldung.hibernate.pojo.*;
import com.baeldung.hibernate.pojo.PointEntity; import com.baeldung.hibernate.pojo.Person;
import com.baeldung.hibernate.pojo.PolygonEntity; import com.baeldung.hibernate.pojo.inheritance.*;
import com.baeldung.hibernate.pojo.Product;
import com.baeldung.hibernate.pojo.Phone;
import com.baeldung.hibernate.pojo.TemporalValues;
import com.baeldung.hibernate.pojo.Course;
import com.baeldung.hibernate.pojo.Student;
import com.baeldung.hibernate.pojo.User;
import com.baeldung.hibernate.pojo.UserProfile;
import com.baeldung.hibernate.pojo.inheritance.Animal;
import com.baeldung.hibernate.pojo.inheritance.Bag;
import com.baeldung.hibernate.pojo.inheritance.Book;
import com.baeldung.hibernate.pojo.inheritance.Car;
import com.baeldung.hibernate.pojo.inheritance.MyEmployee;
import com.baeldung.hibernate.pojo.inheritance.MyProduct;
import com.baeldung.hibernate.pojo.inheritance.Pen;
import com.baeldung.hibernate.pojo.inheritance.Person;
import com.baeldung.hibernate.pojo.inheritance.Pet;
import com.baeldung.hibernate.pojo.inheritance.Vehicle;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
@ -82,6 +64,12 @@ public class HibernateUtil {
metadataSources.addAnnotatedClass(PointEntity.class); metadataSources.addAnnotatedClass(PointEntity.class);
metadataSources.addAnnotatedClass(PolygonEntity.class); metadataSources.addAnnotatedClass(PolygonEntity.class);
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pojo.Person.class); metadataSources.addAnnotatedClass(com.baeldung.hibernate.pojo.Person.class);
metadataSources.addAnnotatedClass(Individual.class);
metadataSources.addAnnotatedClass(PessimisticLockingEmployee.class);
metadataSources.addAnnotatedClass(PessimisticLockingStudent.class);
metadataSources.addAnnotatedClass(PessimisticLockingCourse.class);
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Customer.class);
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Address.class);
Metadata metadata = metadataSources.buildMetadata(); Metadata metadata = metadataSources.buildMetadata();
return metadata.getSessionFactoryBuilder() return metadata.getSessionFactoryBuilder()

View File

@ -0,0 +1,34 @@
package com.baeldung.hibernate.pessimisticlocking;
import javax.persistence.Embeddable;
@Embeddable
public class Address {
private String country;
private String city;
public Address(String country, String city) {
this.country = country;
this.city = city;
}
public Address() {
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}

View File

@ -0,0 +1,58 @@
package com.baeldung.hibernate.pessimisticlocking;
import javax.persistence.*;
import java.util.List;
@Entity
public class Customer {
@Id
private Long customerId;
private String name;
private String lastName;
@ElementCollection
@CollectionTable(name = "customer_address")
private List<Address> addressList;
public Customer() {
}
public Customer(Long customerId, String name, String lastName, List<Address> addressList) {
this.customerId = customerId;
this.name = name;
this.lastName = lastName;
this.addressList = addressList;
}
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<Address> getAddressList() {
return addressList;
}
public void setAddressList(List<Address> addressList) {
this.addressList = addressList;
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.hibernate.pessimisticlocking;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Individual {
@Id
private Long id;
private String name;
private String lastName;
public Individual(Long id, String name, String lastName) {
this.id = id;
this.name = name;
this.lastName = lastName;
}
public Individual() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.hibernate.pessimisticlocking;
import javax.persistence.*;
@Entity
public class PessimisticLockingCourse {
@Id
private Long courseId;
private String name;
@ManyToOne
@JoinTable(name = "student_course")
private PessimisticLockingStudent student;
public PessimisticLockingCourse(Long courseId, String name, PessimisticLockingStudent student) {
this.courseId = courseId;
this.name = name;
this.student = student;
}
public PessimisticLockingCourse() {
}
public Long getCourseId() {
return courseId;
}
public void setCourseId(Long courseId) {
this.courseId = courseId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public PessimisticLockingStudent getStudent() {
return student;
}
public void setStudent(PessimisticLockingStudent students) {
this.student = students;
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.hibernate.pessimisticlocking;
import javax.persistence.Entity;
import java.math.BigDecimal;
@Entity
public class PessimisticLockingEmployee extends Individual {
private BigDecimal salary;
public PessimisticLockingEmployee(Long id, String name, String lastName, BigDecimal salary) {
super(id, name, lastName);
this.salary = salary;
}
public PessimisticLockingEmployee() {
super();
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal average) {
this.salary = average;
}
}

View File

@ -0,0 +1,46 @@
package com.baeldung.hibernate.pessimisticlocking;
import javax.persistence.*;
import java.util.List;
@Entity
public class PessimisticLockingStudent {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "student")
private List<PessimisticLockingCourse> courses;
public PessimisticLockingStudent(Long id, String name) {
this.id = id;
this.name = name;
}
public PessimisticLockingStudent() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<PessimisticLockingCourse> getCourses() {
return courses;
}
public void setCourses(List<PessimisticLockingCourse> courses) {
this.courses = courses;
}
}

View File

@ -0,0 +1,151 @@
package com.baeldung.hibernate.pessimisticlocking;
import com.baeldung.hibernate.HibernateUtil;
import com.vividsolutions.jts.util.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.persistence.*;
import java.io.IOException;
import java.util.Arrays;
public class BasicPessimisticLockingIntegrationTest {
@BeforeClass
public static void setUp() throws IOException {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent student = new PessimisticLockingStudent(1L, "JOHN");
PessimisticLockingCourse course = new PessimisticLockingCourse(1L, "MATH", student);
student.setCourses(Arrays.asList(course));
entityManager.persist(course);
entityManager.persist(student);
entityManager.getTransaction()
.commit();
entityManager.close();
}
@Test
public void givenFoundRecordWithPessimisticRead_whenFindingNewOne_PessimisticLockExceptionThrown() {
try {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
entityManager.find(PessimisticLockingStudent.class, 1L, LockModeType.PESSIMISTIC_READ);
EntityManager entityManager2 = getEntityManagerWithOpenTransaction();
entityManager2.find(PessimisticLockingStudent.class, 1L, LockModeType.PESSIMISTIC_READ);
entityManager.close();
entityManager2.close();
} catch (Exception e) {
Assert.isTrue(e instanceof PessimisticLockException);
}
}
@Test
public void givenRecordWithPessimisticReadQuery_whenQueryingNewOne_PessimisticLockExceptionThrown() throws IOException {
try {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
Query query = entityManager.createQuery("from Student where studentId = :studentId");
query.setParameter("studentId", 1L);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
query.getResultList();
EntityManager entityManager2 = getEntityManagerWithOpenTransaction();
Query query2 = entityManager2.createQuery("from Student where studentId = :studentId");
query2.setParameter("studentId", 1L);
query2.setLockMode(LockModeType.PESSIMISTIC_READ);
query2.getResultList();
entityManager.close();
entityManager2.close();
} catch (Exception e) {
Assert.isTrue(e instanceof PessimisticLockException);
}
}
@Test
public void givenRecordWithPessimisticReadLock_whenFindingNewOne_PessimisticLockExceptionThrown() {
try {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent resultStudent = entityManager.find(PessimisticLockingStudent.class, 1L);
entityManager.lock(resultStudent, LockModeType.PESSIMISTIC_READ);
EntityManager entityManager2 = getEntityManagerWithOpenTransaction();
entityManager2.find(PessimisticLockingStudent.class, 1L, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
entityManager.close();
entityManager2.close();
} catch (Exception e) {
Assert.isTrue(e instanceof PessimisticLockException);
}
}
@Test
public void givenRecordAndRefreshWithPessimisticRead_whenFindingWithPessimisticWrite_PessimisticLockExceptionThrown() {
try {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent resultStudent = entityManager.find(PessimisticLockingStudent.class, 1L);
entityManager.refresh(resultStudent, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
EntityManager entityManager2 = getEntityManagerWithOpenTransaction();
entityManager2.find(PessimisticLockingStudent.class, 1L, LockModeType.PESSIMISTIC_WRITE);
entityManager.close();
entityManager2.close();
} catch (Exception e) {
Assert.isTrue(e instanceof PessimisticLockException);
}
}
@Test
public void givenRecordWithPessimisticRead_whenUpdatingRecord_PessimisticLockExceptionThrown() {
try {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent resultStudent = entityManager.find(PessimisticLockingStudent.class, 1L);
entityManager.refresh(resultStudent, LockModeType.PESSIMISTIC_READ);
EntityManager entityManager2 = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent resultStudent2 = entityManager2.find(PessimisticLockingStudent.class, 1L);
resultStudent2.setName("Change");
entityManager2.persist(resultStudent2);
entityManager2.getTransaction()
.commit();
entityManager.close();
entityManager2.close();
} catch (Exception e) {
Assert.isTrue(e instanceof PessimisticLockException);
}
}
@Test
public void givenRecordWithPessimisticWrite_whenUpdatingRecord_PessimisticLockExceptionThrown() {
try {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent resultStudent = entityManager.find(PessimisticLockingStudent.class, 1L);
entityManager.refresh(resultStudent, LockModeType.PESSIMISTIC_WRITE);
EntityManager entityManager2 = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent resultStudent2 = entityManager2.find(PessimisticLockingStudent.class, 1L);
resultStudent2.setName("Change");
entityManager2.persist(resultStudent2);
entityManager2.getTransaction()
.commit();
entityManager.close();
entityManager2.close();
} catch (Exception e) {
Assert.isTrue(e instanceof PessimisticLockException);
}
}
protected static EntityManager getEntityManagerWithOpenTransaction() throws IOException {
String propertyFileName = "hibernate-pessimistic-locking.properties";
EntityManager entityManager = HibernateUtil.getSessionFactory(propertyFileName)
.openSession();
entityManager.getTransaction()
.begin();
return entityManager;
}
}

View File

@ -0,0 +1,100 @@
package com.baeldung.hibernate.pessimisticlocking;
import com.baeldung.hibernate.HibernateUtil;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.PessimisticLockScope;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class PessimisticLockScopesIntegrationTest {
@Test
public void givenEclipseEntityWithJoinInheritance_whenNormalLock_thenShouldChildAndParentEntity() throws IOException {
EntityManager em = getEntityManagerWithOpenTransaction();
PessimisticLockingEmployee employee = new PessimisticLockingEmployee(1L, "A", "B", new BigDecimal(4.5));
em.persist(employee);
em.getTransaction()
.commit();
em.close();
// NORMAL SCOPE
em = getEntityManagerWithOpenTransaction();
PessimisticLockingEmployee foundEmployee = em.find(PessimisticLockingEmployee.class, 1L, LockModeType.PESSIMISTIC_WRITE);
em.getTransaction()
.rollback();
// EXTENDED SCOPE
Map<String, Object> map = new HashMap<>();
map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED);
em = getEntityManagerWithOpenTransaction();
foundEmployee = em.find(PessimisticLockingEmployee.class, 1L, LockModeType.PESSIMISTIC_WRITE, map);
}
@Test
public void givenEclipseEntityWithElementCollection_whenNormalLock_thenShouldLockOnlyOwningEntity() throws IOException {
EntityManager em = getEntityManagerWithOpenTransaction();
Address address = new Address("Poland", "Warsaw");
Customer customer = new Customer(1L, "A", "B", Arrays.asList(address));
em.persist(customer);
em.getTransaction()
.commit();
em.close();
// NORMAL SCOPE
em = getEntityManagerWithOpenTransaction();
Customer foundCustomer = em.find(Customer.class, 1L, LockModeType.PESSIMISTIC_WRITE);
em.getTransaction()
.rollback();
// EXTENDED SCOPE
Map<String, Object> map = new HashMap<>();
map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED);
em = getEntityManagerWithOpenTransaction();
foundCustomer = em.find(Customer.class, 1L, LockModeType.PESSIMISTIC_WRITE, map);
}
@Test
public void givenEclipseEntityWithOneToMany_whenNormalLock_thenShouldLockOnlyOwningEntity() throws IOException {
EntityManager em = getEntityManagerWithOpenTransaction();
PessimisticLockingStudent student = new PessimisticLockingStudent(1L, "JOE");
PessimisticLockingCourse course = new PessimisticLockingCourse(1L, "COURSE", student);
student.setCourses(Arrays.asList(course));
em.persist(course);
em.persist(student);
em.getTransaction()
.commit();
em.close();
// NORMAL SCOPE
em = getEntityManagerWithOpenTransaction();
PessimisticLockingCourse foundCourse = em.find(PessimisticLockingCourse.class, 1L, LockModeType.PESSIMISTIC_WRITE);
em.getTransaction()
.rollback();
// EXTENDED SCOPE
Map<String, Object> map = new HashMap<>();
map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED);
em = getEntityManagerWithOpenTransaction();
foundCourse = em.find(PessimisticLockingCourse.class, 1L, LockModeType.PESSIMISTIC_WRITE, map);
}
protected EntityManager getEntityManagerWithOpenTransaction() throws IOException {
String propertyFileName = "hibernate-pessimistic-locking.properties";
EntityManager entityManager = HibernateUtil.getSessionFactory(propertyFileName)
.openSession();
entityManager.getTransaction()
.begin();
return entityManager;
}
}

View File

@ -0,0 +1,8 @@
hibernate.connection.driver_class=org.h2.Driver
hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=100;MVCC=FALSE
hibernate.connection.username=sa
hibernate.connection.autocommit=true
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create-drop

View File

@ -0,0 +1,34 @@
package com.baeldung.eclipselink.springdata.pessimisticlocking;
import javax.persistence.Embeddable;
@Embeddable
public class Address {
private String country;
private String city;
public Address(String country, String city) {
this.country = country;
this.city = city;
}
public Address() {
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.eclipselink.springdata.pessimisticlocking;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
@Entity
public class Course {
@Id
private Long courseId;
private String name;
@ManyToOne
@JoinTable(name = "student_course")
private Student student;
public Course(Long courseId, String name, Student student) {
this.courseId = courseId;
this.name = name;
this.student = student;
}
public Course() {
}
public Long getCourseId() {
return courseId;
}
public void setCourseId(Long courseId) {
this.courseId = courseId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStudent() {
return student;
}
public void setStudent(Student students) {
this.student = students;
}
}

View File

@ -0,0 +1,61 @@
package com.baeldung.eclipselink.springdata.pessimisticlocking;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.List;
@Entity
public class Customer {
@Id
private Long customerId;
private String name;
private String lastName;
@ElementCollection
@CollectionTable(name = "customer_address")
private List<Address> addressList;
public Customer() {
}
public Customer(Long customerId, String name, String lastName, List<Address> addressList) {
this.customerId = customerId;
this.name = name;
this.lastName = lastName;
this.addressList = addressList;
}
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<Address> getAddressList() {
return addressList;
}
public void setAddressList(List<Address> addressList) {
this.addressList = addressList;
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.eclipselink.springdata.pessimisticlocking;
import javax.persistence.Entity;
import java.math.BigDecimal;
@Entity
public class Employee extends Individual {
private BigDecimal salary;
public Employee(Long id, String name, String lastName, BigDecimal salary) {
super(id, name, lastName);
this.salary = salary;
}
public Employee() {
super();
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal average) {
this.salary = average;
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.eclipselink.springdata.pessimisticlocking;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Individual {
@Id
private Long id;
private String name;
private String lastName;
public Individual(Long id, String name, String lastName) {
this.id = id;
this.name = name;
this.lastName = lastName;
}
public Individual() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

View File

@ -0,0 +1,48 @@
package com.baeldung.eclipselink.springdata.pessimisticlocking;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.List;
@Entity
public class Student {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "student")
private List<Course> courses;
public Student(Long id, String name) {
this.id = id;
this.name = name;
}
public Student() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
}

View File

@ -1,2 +1,2 @@
spring.datasource.url=jdbc:h2:mem:test spring.datasource.url=jdbc:h2:mem:test;MVCC=FALSE;LOCK_TIMEOUT=100;
spring.jpa.show-sql=true spring.jpa.show-sql=true

View File

@ -0,0 +1,103 @@
package com.baeldung.eclipselink.springdata.pessimisticlocking;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class PessimisticLockScopesIntegrationTest {
@Autowired
EntityManagerFactory entityManagerFactory;
@Test
public void givenEclipseEntityWithJoinInheritance_whenNormalLock_thenShouldChildAndParentEntity() {
EntityManager em = getEntityManagerWithOpenTransaction();
Employee employee = new Employee(1L, "A", "B", new BigDecimal(4.5));
em.persist(employee);
em.getTransaction()
.commit();
em.close();
// NORMAL SCOPE
em = getEntityManagerWithOpenTransaction();
Employee foundEmployee = em.find(Employee.class, 1L, LockModeType.PESSIMISTIC_WRITE);
em.getTransaction()
.rollback();
// EXTENDED SCOPE
Map<String, Object> map = new HashMap<>();
map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED);
em = getEntityManagerWithOpenTransaction();
foundEmployee = em.find(Employee.class, 1L, LockModeType.PESSIMISTIC_WRITE, map);
}
@Test
public void givenEclipseEntityWithElementCollection_whenNormalLock_thenShouldLockOnlyOwningEntity() {
EntityManager em = getEntityManagerWithOpenTransaction();
Address address = new Address("Poland", "Warsaw");
Customer customer = new Customer(1L, "A", "B", Arrays.asList(address));
em.persist(customer);
em.getTransaction()
.commit();
em.close();
// NORMAL SCOPE
em = getEntityManagerWithOpenTransaction();
Customer foundCustomer = em.find(Customer.class, 1L, LockModeType.PESSIMISTIC_WRITE);
em.getTransaction()
.rollback();
// EXTENDED SCOPE
Map<String, Object> map = new HashMap<>();
map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED);
em = getEntityManagerWithOpenTransaction();
foundCustomer = em.find(Customer.class, 1L, LockModeType.PESSIMISTIC_WRITE, map);
}
@Test
public void givenEclipseEntityWithOneToMany_whenNormalLock_thenShouldLockOnlyOwningEntity() {
EntityManager em = getEntityManagerWithOpenTransaction();
Student student = new Student(1L, "JOE");
Course course = new Course(1L, "COURSE", student);
student.setCourses(Arrays.asList(course));
em.persist(course);
em.persist(student);
em.getTransaction()
.commit();
em.close();
// NORMAL SCOPE
em = getEntityManagerWithOpenTransaction();
Course foundCourse = em.find(Course.class, 1L, LockModeType.PESSIMISTIC_WRITE);
em.getTransaction()
.rollback();
// EXTENDED SCOPE
Map<String, Object> map = new HashMap<>();
map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED);
em = getEntityManagerWithOpenTransaction();
foundCourse = em.find(Course.class, 1L, LockModeType.PESSIMISTIC_WRITE, map);
}
protected EntityManager getEntityManagerWithOpenTransaction() {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction()
.begin();
return entityManager;
}
}