BAEL-1730: Optimistic Locking in JPA

Tests for the article.
This commit is contained in:
Patryk Kucharz 2018-06-12 18:22:32 +02:00 committed by José Carlos Valero Sánchez
parent 7afbfb6968
commit fc14d426c5
4 changed files with 256 additions and 0 deletions

View File

@ -1,5 +1,7 @@
package com.baeldung.hibernate;
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingCourse;
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingStudent;
import com.baeldung.hibernate.pessimisticlocking.Individual;
import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingCourse;
import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingEmployee;
@ -70,6 +72,8 @@ public class HibernateUtil {
metadataSources.addAnnotatedClass(PessimisticLockingCourse.class);
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Customer.class);
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Address.class);
metadataSources.addAnnotatedClass(OptimisticLockingCourse.class);
metadataSources.addAnnotatedClass(OptimisticLockingStudent.class);
Metadata metadata = metadataSources.buildMetadata();
return metadata.getSessionFactoryBuilder()

View File

@ -0,0 +1,48 @@
package com.baeldung.hibernate.optimisticlocking;
import javax.persistence.*;
@Entity
public class OptimisticLockingCourse {
@Id
private Long id;
private String name;
@ManyToOne
@JoinTable(name = "optimistic_student_course")
private OptimisticLockingStudent student;
public OptimisticLockingCourse(Long id, String name) {
this.id = id;
this.name = name;
}
public OptimisticLockingCourse() {
}
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 OptimisticLockingStudent getStudent() {
return student;
}
public void setStudent(OptimisticLockingStudent student) {
this.student = student;
}
}

View File

@ -0,0 +1,70 @@
package com.baeldung.hibernate.optimisticlocking;
import javax.persistence.*;
import java.util.List;
@Entity
public class OptimisticLockingStudent {
@Id
private Long id;
private String name;
private String lastName;
@Version
private Integer version;
@OneToMany(mappedBy = "student")
private List<OptimisticLockingCourse> courses;
public OptimisticLockingStudent(Long id, String name, String lastName, List<OptimisticLockingCourse> courses) {
this.id = id;
this.name = name;
this.lastName = lastName;
this.courses = courses;
}
public OptimisticLockingStudent() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
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<OptimisticLockingCourse> getCourses() {
return courses;
}
public void setCourses(List<OptimisticLockingCourse> courses) {
this.courses = courses;
}
}

View File

@ -0,0 +1,134 @@
package com.baeldung.hibernate.optimisticlocking;
import com.baeldung.hibernate.HibernateUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.OptimisticLockException;
import java.io.IOException;
import java.util.Arrays;
public class OptimisticLockingIntegrationTest {
@Before
public void setUp() throws IOException {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
OptimisticLockingCourse course = new OptimisticLockingCourse(1L, "MATH");
OptimisticLockingStudent student = new OptimisticLockingStudent(1L, "John", "Doe", Arrays.asList(course));
course.setStudent(student);
entityManager.persist(course);
entityManager.persist(student);
entityManager.getTransaction()
.commit();
entityManager.close();
}
@After
public void clean() throws IOException {
EntityManager entityManager = getEntityManagerWithOpenTransaction();
OptimisticLockingCourse course = entityManager.find(OptimisticLockingCourse.class, 1L);
OptimisticLockingStudent student = entityManager.find(OptimisticLockingStudent.class, 1L);
entityManager.remove(course);
entityManager.remove(student);
entityManager.getTransaction()
.commit();
entityManager.close();
}
@Test(expected = OptimisticLockException.class)
public void givenVersionedEntities_whenConcurrentUpdate_thenOptimisticLockException() throws IOException {
EntityManager em = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student = em.find(OptimisticLockingStudent.class, 1L);
EntityManager em2 = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student2 = em2.find(OptimisticLockingStudent.class, 1L);
student2.setName("RICHARD");
em2.persist(student2);
em2.getTransaction()
.commit();
em2.close();
student.setName("JOHN");
em.persist(student);
em.getTransaction()
.commit();
em.close();
}
@Test(expected = OptimisticLockException.class)
public void givenVersionedEntitiesWithLockByFindMethod_whenConcurrentUpdate_thenOptimisticLockException() throws IOException {
EntityManager em = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student = em.find(OptimisticLockingStudent.class, 1L, LockModeType.OPTIMISTIC);
EntityManager em2 = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student2 = em2.find(OptimisticLockingStudent.class, 1L, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
student2.setName("RICHARD");
em2.persist(student2);
em2.getTransaction()
.commit();
em2.close();
student.setName("JOHN");
em.persist(student);
em.getTransaction()
.commit();
em.close();
}
@Test(expected = OptimisticLockException.class)
public void givenVersionedEntitiesWithLockByRefreshMethod_whenConcurrentUpdate_thenOptimisticLockException() throws IOException {
EntityManager em = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student = em.find(OptimisticLockingStudent.class, 1L);
em.refresh(student, LockModeType.OPTIMISTIC);
EntityManager em2 = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student2 = em2.find(OptimisticLockingStudent.class, 1L);
em.refresh(student, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
student2.setName("RICHARD");
em2.persist(student2);
em2.getTransaction()
.commit();
em2.close();
student.setName("JOHN");
em.persist(student);
em.getTransaction()
.commit();
em.close();
}
@Test(expected = OptimisticLockException.class)
public void givenVersionedEntitiesWithLockByLockMethod_whenConcurrentUpdate_thenOptimisticLockException() throws IOException {
EntityManager em = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student = em.find(OptimisticLockingStudent.class, 1L);
em.lock(student, LockModeType.OPTIMISTIC);
EntityManager em2 = getEntityManagerWithOpenTransaction();
OptimisticLockingStudent student2 = em2.find(OptimisticLockingStudent.class, 1L);
em.lock(student, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
student2.setName("RICHARD");
em2.persist(student2);
em2.getTransaction()
.commit();
em2.close();
student.setName("JOHN");
em.persist(student);
em.getTransaction()
.commit();
em.close();
}
protected static EntityManager getEntityManagerWithOpenTransaction() throws IOException {
String propertyFileName = "hibernate-pessimistic-locking.properties";
EntityManager entityManager = HibernateUtil.getSessionFactory(propertyFileName)
.openSession();
entityManager.getTransaction()
.begin();
return entityManager;
}
}