BAEL-1713: Pessimistic Locking in JPA
Tests for the article.
This commit is contained in:
+34
@@ -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;
|
||||
}
|
||||
}
|
||||
+50
@@ -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;
|
||||
}
|
||||
}
|
||||
+61
@@ -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;
|
||||
}
|
||||
}
|
||||
+27
@@ -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;
|
||||
}
|
||||
}
|
||||
+49
@@ -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;
|
||||
}
|
||||
}
|
||||
+48
@@ -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
-1
@@ -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
|
||||
+103
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user