/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.userguide.locking; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.LockModeType; import javax.persistence.PessimisticLockScope; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.Session; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.query.Query; import org.hibernate.testing.RequiresDialect; import org.junit.Test; import org.jboss.logging.Logger; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; import static org.junit.Assert.assertEquals; /** * @author Vlad Mihalcea */ public class ExplicitLockingTest extends BaseEntityManagerFunctionalTestCase { private static final Logger log = Logger.getLogger( ExplicitLockingTest.class ); @Override protected Class<?>[] getAnnotatedClasses() { return new Class<?>[] { Person.class, Phone.class, }; } @Test public void testJPALockTimeout() { doInJPA( this::entityManagerFactory, entityManager -> { Person person = new Person( "John Doe" ); entityManager.persist( person ); } ); doInJPA( this::entityManagerFactory, entityManager -> { log.info( "testJPALockTimeout" ); Long id = 1L; //tag::locking-jpa-query-hints-timeout-example[] entityManager.find( Person.class, id, LockModeType.PESSIMISTIC_WRITE, Collections.singletonMap( "javax.persistence.lock.timeout", 200 ) ); //end::locking-jpa-query-hints-timeout-example[] } ); } @Test public void testJPALockScope() { doInJPA( this::entityManagerFactory, entityManager -> { Person person = new Person( "John Doe" ); entityManager.persist( person ); Phone home = new Phone( "123-456-7890" ); Phone office = new Phone( "098-765-4321" ); person.getPhones().add( home ); person.getPhones().add( office ); entityManager.persist( person ); } ); doInJPA( this::entityManagerFactory, entityManager -> { log.info( "testJPALockScope" ); Long id = 1L; //tag::locking-jpa-query-hints-scope-example[] Person person = entityManager.find( Person.class, id, LockModeType.PESSIMISTIC_WRITE, Collections.singletonMap( "javax.persistence.lock.scope", PessimisticLockScope.EXTENDED ) ); //end::locking-jpa-query-hints-scope-example[] assertEquals( 2, person.getPhones().size() ); } ); } @Test public void testBuildLockRequest() { doInJPA( this::entityManagerFactory, entityManager -> { log.info( "testBuildLockRequest" ); Person person = new Person( "John Doe" ); Phone home = new Phone( "123-456-7890" ); Phone office = new Phone( "098-765-4321" ); person.getPhones().add( home ); person.getPhones().add( office ); entityManager.persist( person ); entityManager.flush(); } ); doInJPA( this::entityManagerFactory, entityManager -> { Long id = 1L; //tag::locking-buildLockRequest-example[] Person person = entityManager.find( Person.class, id ); Session session = entityManager.unwrap( Session.class ); session .buildLockRequest( LockOptions.NONE ) .setLockMode( LockMode.PESSIMISTIC_READ ) .setTimeOut( LockOptions.NO_WAIT ) .lock( person ); //end::locking-buildLockRequest-example[] } ); doInJPA( this::entityManagerFactory, entityManager -> { Long id = 1L; //tag::locking-buildLockRequest-scope-example[] Person person = entityManager.find( Person.class, id ); Session session = entityManager.unwrap( Session.class ); session .buildLockRequest( LockOptions.NONE ) .setLockMode( LockMode.PESSIMISTIC_READ ) .setTimeOut( LockOptions.NO_WAIT ) .setScope( true ) .lock( person ); //end::locking-buildLockRequest-scope-example[] } ); } @Test @RequiresDialect(Oracle8iDialect.class) public void testFollowOnLocking() { doInJPA( this::entityManagerFactory, entityManager -> { log.info( "testBuildLockRequest" ); Person person1 = new Person( "John Doe" ); Person person2 = new Person( "Mrs. John Doe" ); entityManager.persist( person1 ); entityManager.persist( person2 ); entityManager.flush(); } ); doInJPA( this::entityManagerFactory, entityManager -> { //tag::locking-follow-on-example[] List<Person> persons = entityManager.createQuery( "select DISTINCT p from Person p", Person.class) .setLockMode( LockModeType.PESSIMISTIC_WRITE ) .getResultList(); //end::locking-follow-on-example[] } ); doInJPA( this::entityManagerFactory, entityManager -> { //tag::locking-follow-on-secondary-query-example[] List<Person> persons = entityManager.createQuery( "select DISTINCT p from Person p", Person.class) .getResultList(); entityManager.createQuery( "select p.id from Person p where p in :persons") .setLockMode( LockModeType.PESSIMISTIC_WRITE ) .setParameter( "persons", persons ) .getResultList(); //end::locking-follow-on-secondary-query-example[] } ); doInJPA( this::entityManagerFactory, entityManager -> { //tag::locking-follow-on-explicit-example[] List<Person> persons = entityManager.createQuery( "select p from Person p", Person.class) .setMaxResults( 10 ) .unwrap( Query.class ) .setLockOptions( new LockOptions( LockMode.PESSIMISTIC_WRITE ) .setFollowOnLocking( false ) ) .getResultList(); //end::locking-follow-on-explicit-example[] } ); } //tag::locking-jpa-query-hints-scope-entity-example[] @Entity(name = "Person") public static class Person { @Id @GeneratedValue private Long id; @Column(name = "`name`") private String name; @ElementCollection @JoinTable(name = "person_phone", joinColumns = @JoinColumn(name = "person_id")) private List<Phone> phones = new ArrayList<>(); public Person() { } public Person(String name) { this.name = name; } public Long getId() { return id; } public String getName() { return name; } public List<Phone> getPhones() { return phones; } } @Embeddable public static class Phone { @Column private String mobile; public Phone() {} public Phone(String mobile) { this.mobile = mobile; } } //end::locking-jpa-query-hints-scope-entity-example[] }