From 719e5d0c12a6ef709bee907b8b651d27b8b08a6a Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 23 Jul 2018 17:10:22 +0200 Subject: [PATCH] HHH-12847 Consider LockOptions for getting the LockMode Otherwise, it leads to null pointer exceptions. --- .../AbstractLoadPlanBasedEntityLoader.java | 9 +- ...oaderInitializationWithNoLockModeTest.java | 114 ++++++++++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/batchfetch/BatchingEntityLoaderInitializationWithNoLockModeTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/loader/entity/plan/AbstractLoadPlanBasedEntityLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/entity/plan/AbstractLoadPlanBasedEntityLoader.java index 2fb8af6e09..5beadbe812 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/entity/plan/AbstractLoadPlanBasedEntityLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/entity/plan/AbstractLoadPlanBasedEntityLoader.java @@ -65,17 +65,20 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan final LoadPlanBuildingAssociationVisitationStrategy strategy; if ( buildingParameters.getQueryInfluencers().getFetchGraph() != null ) { strategy = new FetchGraphLoadPlanBuildingStrategy( - factory, buildingParameters.getQueryInfluencers(),buildingParameters.getLockMode() + factory, buildingParameters.getQueryInfluencers(), + buildingParameters.getLockOptions() != null ? buildingParameters.getLockOptions().getLockMode() : buildingParameters.getLockMode() ); } else if ( buildingParameters.getQueryInfluencers().getLoadGraph() != null ) { strategy = new LoadGraphLoadPlanBuildingStrategy( - factory, buildingParameters.getQueryInfluencers(),buildingParameters.getLockMode() + factory, buildingParameters.getQueryInfluencers(), + buildingParameters.getLockOptions() != null ? buildingParameters.getLockOptions().getLockMode() : buildingParameters.getLockMode() ); } else { strategy = new FetchStyleLoadPlanBuildingAssociationVisitationStrategy( - factory, buildingParameters.getQueryInfluencers(),buildingParameters.getLockMode() + factory, buildingParameters.getQueryInfluencers(), + buildingParameters.getLockOptions() != null ? buildingParameters.getLockOptions().getLockMode() : buildingParameters.getLockMode() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/batchfetch/BatchingEntityLoaderInitializationWithNoLockModeTest.java b/hibernate-core/src/test/java/org/hibernate/test/batchfetch/BatchingEntityLoaderInitializationWithNoLockModeTest.java new file mode 100644 index 0000000000..461e57c7a8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/batchfetch/BatchingEntityLoaderInitializationWithNoLockModeTest.java @@ -0,0 +1,114 @@ +package org.hibernate.test.batchfetch; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertNotNull; + +import java.util.Map; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.annotations.Fetch; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.loader.BatchFetchStyle; +import org.hibernate.metamodel.spi.MetamodelImplementor; +import org.hibernate.persister.entity.EntityPersister; +import org.junit.Test; + +public class BatchingEntityLoaderInitializationWithNoLockModeTest extends BaseEntityManagerFunctionalTestCase { + + private Long mainId; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { MainEntity.class, SubEntity.class }; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + protected Map buildSettings() { + Map settings = super.buildSettings(); + settings.put( AvailableSettings.BATCH_FETCH_STYLE, BatchFetchStyle.LEGACY ); + settings.put( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, 5 ); + return settings; + } + + @Test + public void testJoin() { + doInJPA( this::entityManagerFactory, em -> { + SubEntity sub = new SubEntity(); + em.persist( sub ); + + MainEntity main = new MainEntity(); + main.setSub( sub ); + em.persist( main ); + + this.mainId = main.getId(); + }); + + doInJPA( this::entityManagerFactory, em -> { + EntityPersister entityPersister = ( (MetamodelImplementor) em.getMetamodel() ) + .entityPersister( MainEntity.class ); + + // use some specific lock options to trigger the creation of a loader with lock options + LockOptions lockOptions = new LockOptions( LockMode.NONE ); + lockOptions.setTimeOut( 10 ); + + MainEntity main = (MainEntity) entityPersister.load( this.mainId, null, lockOptions, + (SharedSessionContractImplementor) em ); + assertNotNull( main.getSub() ); + } ); + } + + @Entity(name = "MainEntity") + public static class MainEntity { + + @Id + @GeneratedValue + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @Fetch(org.hibernate.annotations.FetchMode.JOIN) + private SubEntity sub; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public SubEntity getSub() { + return sub; + } + + public void setSub(SubEntity sub) { + this.sub = sub; + } + } + + @Entity(name = "SubEntity") + public static class SubEntity { + + @Id + @GeneratedValue + private Long id; + + public Long getId() { + return id; + } + + + public void setId(Long id) { + this.id = id; + } + } +}