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
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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
@@ -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;
}
}