HHH-11970 : @NotFound(IGNORE) and @BatchSize
This commit is contained in:
parent
87a37b02f4
commit
19087d9f15
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.engine.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.engine.spi.BatchFetchQueue;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class BatchFetchQueueHelper {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
BatchFetchQueueHelper.class.getName()
|
||||
);
|
||||
|
||||
private BatchFetchQueueHelper(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the IDs for entities that were not found when the batch was loaded, and removes
|
||||
* the corresponding entity keys from the {@link BatchFetchQueue}.
|
||||
*
|
||||
* @param ids - the IDs for the entities that were batch loaded
|
||||
* @param results - the results from loading the batch
|
||||
* @param persister - the entity persister for the entities in batch
|
||||
* @param session - the session
|
||||
*/
|
||||
public static void removeNotFoundBatchLoadableEntityKeys(
|
||||
Serializable[] ids,
|
||||
List<?> results,
|
||||
EntityPersister persister,
|
||||
SharedSessionContractImplementor session) {
|
||||
if ( !persister.isBatchLoadable() ) {
|
||||
return;
|
||||
}
|
||||
if ( ids.length == results.size() ) {
|
||||
return;
|
||||
}
|
||||
LOG.debug( "Not all entities were loaded." );
|
||||
Set<Serializable> idSet = new HashSet<>( Arrays.asList( ids ) );
|
||||
for ( Object result : results ) {
|
||||
final Serializable id = session.getPersistenceContext().getEntry( result ).getId();
|
||||
idSet.remove( id );
|
||||
}
|
||||
assert idSet.size() == ids.length - results.size();
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debug( "Entities of type [" + persister.getEntityName() + "] not found; IDs: " + idSet );
|
||||
}
|
||||
for ( Serializable id : idSet ) {
|
||||
removeBatchLoadableEntityKey( id, persister, session );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the entity key with the specified {@code id} and {@code persister} from
|
||||
* the batch loadable entities {@link BatchFetchQueue}.
|
||||
*
|
||||
* @param id - the ID for the entity to be removed
|
||||
* @param persister - the entity persister
|
||||
* @param session - the session
|
||||
*/
|
||||
public static void removeBatchLoadableEntityKey(
|
||||
Serializable id,
|
||||
EntityPersister persister,
|
||||
SharedSessionContractImplementor session) {
|
||||
final EntityKey entityKey = session.generateEntityKey( id, persister );
|
||||
final BatchFetchQueue batchFetchQueue = session.getPersistenceContext().getBatchFetchQueue();
|
||||
batchFetchQueue.removeBatchLoadableEntityKey( entityKey );
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.Loader;
|
||||
|
@ -97,6 +98,15 @@ public abstract class BatchingEntityLoader implements UniqueEntityLoader {
|
|||
try {
|
||||
final List results = loaderToUse.doQueryAndInitializeNonLazyCollections( session, qp, false );
|
||||
log.debug( "Done entity batch load" );
|
||||
// The EntityKey for any entity that is not found will remain in the batch.
|
||||
// Explicitly remove the EntityKeys for entities that were not found to
|
||||
// avoid including them in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeNotFoundBatchLoadableEntityKeys(
|
||||
ids,
|
||||
results,
|
||||
persister(),
|
||||
session
|
||||
);
|
||||
return getObjectFromList(results, id, session);
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.util.List;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.dialect.pagination.LimitHelper;
|
||||
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
|
@ -344,7 +345,13 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
|
|||
|
||||
final int numberOfIds = ArrayHelper.countNonNull( batch );
|
||||
if ( numberOfIds <= 1 ) {
|
||||
return singleKeyLoader.load( id, optionalObject, session );
|
||||
final Object result = singleKeyLoader.load( id, optionalObject, session );
|
||||
if ( result == null ) {
|
||||
// There was no entity with the specified ID. Make sure the EntityKey does not remain
|
||||
// in the batch to avoid including it in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeBatchLoadableEntityKey( id, persister(), session );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
final Serializable[] idsToLoad = new Serializable[numberOfIds];
|
||||
|
@ -356,6 +363,12 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
|
|||
|
||||
QueryParameters qp = buildQueryParameters( id, idsToLoad, optionalObject, lockOptions );
|
||||
List results = dynamicLoader.doEntityBatchFetch( session, qp, idsToLoad );
|
||||
|
||||
// The EntityKey for any entity that is not found will remain in the batch.
|
||||
// Explicitly remove the EntityKeys for entities that were not found to
|
||||
// avoid including them in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeNotFoundBatchLoadableEntityKeys( idsToLoad, results, persister(), session );
|
||||
|
||||
return getObjectFromList( results, id, session );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -100,10 +101,25 @@ public class LegacyBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuild
|
|||
persister(),
|
||||
lockOptions
|
||||
);
|
||||
// The EntityKey for any entity that is not found will remain in the batch.
|
||||
// Explicitly remove the EntityKeys for entities that were not found to
|
||||
// avoid including them in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeNotFoundBatchLoadableEntityKeys(
|
||||
smallBatch,
|
||||
results,
|
||||
persister(),
|
||||
session
|
||||
);
|
||||
return getObjectFromList(results, id, session); //EARLY EXIT
|
||||
}
|
||||
}
|
||||
return ( (UniqueEntityLoader) loaders[batchSizes.length-1] ).load(id, optionalObject, session);
|
||||
final Object result = ( (UniqueEntityLoader) loaders[batchSizes.length-1] ).load(id, optionalObject, session);
|
||||
if ( result == null ) {
|
||||
// There was no entity with the specified ID. Make sure the EntityKey does not remain
|
||||
// in the batch to avoid including it in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeBatchLoadableEntityKey( id, persister(), session );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.io.Serializable;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -96,7 +97,13 @@ class PaddedBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuilder {
|
|||
|
||||
final int numberOfIds = ArrayHelper.countNonNull( batch );
|
||||
if ( numberOfIds <= 1 ) {
|
||||
return ( (UniqueEntityLoader) loaders[batchSizes.length-1] ).load( id, optionalObject, session );
|
||||
final Object result = ( (UniqueEntityLoader) loaders[batchSizes.length-1] ).load( id, optionalObject, session );
|
||||
if ( result == null ) {
|
||||
// There was no entity with the specified ID. Make sure the EntityKey does not remain
|
||||
// in the batch to avoid including it in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeBatchLoadableEntityKey( id, persister(), session );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Uses the first batch-size bigger than the number of actual ids in the batch
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -106,12 +107,27 @@ public class LegacyBatchingEntityLoaderBuilder extends AbstractBatchingEntityLoa
|
|||
persister(),
|
||||
lockOptions
|
||||
);
|
||||
// The EntityKey for any entity that is not found will remain in the batch.
|
||||
// Explicitly remove the EntityKeys for entities that were not found to
|
||||
// avoid including them in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeNotFoundBatchLoadableEntityKeys(
|
||||
smallBatch,
|
||||
results,
|
||||
persister(),
|
||||
session
|
||||
);
|
||||
|
||||
//EARLY EXIT
|
||||
return getObjectFromList( results, id, session );
|
||||
}
|
||||
}
|
||||
return ( loaders[batchSizes.length-1] ).load( id, optionalObject, session, lockOptions );
|
||||
final Object result = ( loaders[batchSizes.length-1] ).load( id, optionalObject, session, lockOptions );
|
||||
if ( result == null ) {
|
||||
// There was no entity with the specified ID. Make sure the EntityKey does not remain
|
||||
// in the batch to avoid including it in future batches that get executed.
|
||||
BatchFetchQueueHelper.removeBatchLoadableEntityKey( id, persister(), session );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* 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.test.batchfetch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.annotations.BatchSize;
|
||||
import org.hibernate.annotations.NotFound;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.spi.BatchFetchQueue;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
* @author Stephen Fikes
|
||||
*/
|
||||
public class BatchFetchNotFoundIgnoreDefaultStyleTest extends BaseCoreFunctionalTestCase {
|
||||
private static final AStatementInspector statementInspector = new AStatementInspector();
|
||||
private static final int NUMBER_OF_EMPLOYEES = 8;
|
||||
|
||||
private List<Task> tasks = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Employee.class, Task.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
super.configure( configuration );
|
||||
configuration.getProperties().put( Environment.STATEMENT_INSPECTOR, statementInspector );
|
||||
}
|
||||
|
||||
@Before
|
||||
public void createData() {
|
||||
tasks.clear();
|
||||
tasks = doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
for (int i = 0 ; i < NUMBER_OF_EMPLOYEES ; i++) {
|
||||
Task task = new Task();
|
||||
task.id = i;
|
||||
tasks.add( task );
|
||||
session.persist( task );
|
||||
Employee e = new Employee("employee0" + i);
|
||||
e.task = task;
|
||||
session.persist(e);
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
public void deleteData() {
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
session.createQuery( "delete from Task" ).executeUpdate();
|
||||
session.createQuery( "delete from Employee" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeveralNotFoundFromQuery() {
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
// delete 2nd and 8th Task so that the non-found Task entities will be queried
|
||||
// in 2 different batches.
|
||||
session.delete( tasks.get( 1 ) );
|
||||
session.delete( tasks.get( 7 ) );
|
||||
}
|
||||
);
|
||||
|
||||
statementInspector.clear();
|
||||
|
||||
final List<Employee> employees = doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
List<Employee> results =
|
||||
session.createQuery( "from Employee e order by e.id", Employee.class ).getResultList();
|
||||
for ( int i = 0 ; i < tasks.size() ; i++ ) {
|
||||
checkInBatchFetchQueue( tasks.get( i ).id, session, false );
|
||||
}
|
||||
return results;
|
||||
}
|
||||
);
|
||||
|
||||
final List<Integer> paramterCounts = statementInspector.parameterCounts;
|
||||
|
||||
// there should be 4 SQL statements executed
|
||||
assertEquals( 4, paramterCounts.size() );
|
||||
|
||||
// query loading Employee entities shouldn't have any parameters
|
||||
assertEquals( 0, paramterCounts.get( 0 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 0 will result in 1st batch;
|
||||
// query should have 5 parameters for [0,1,2,3,4];
|
||||
// Task with ID == 1 won't be found; the rest will be found.
|
||||
assertEquals( 5, paramterCounts.get( 1 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 1 will result in 2nd batch;
|
||||
// query should have 4 parameters [1,5,6,7];
|
||||
// Task with IDs == [1,7] won't be found; the rest will be found.
|
||||
assertEquals( 4, paramterCounts.get( 2 ).intValue() );
|
||||
|
||||
// no extra queries required to load entities with IDs [2,3,4] because they
|
||||
// were already loaded from 1st batch
|
||||
|
||||
// no extra queries required to load entities with IDs [5,6] because they
|
||||
// were already loaded from 2nd batch
|
||||
|
||||
// query specifically for Task with ID == 7 will result in just querying
|
||||
// Task with ID == 7 (because the batch is empty).
|
||||
// query should have 1 parameter [7];
|
||||
// Task with ID == 7 won't be found.
|
||||
assertEquals( 1, paramterCounts.get( 3 ).intValue() );
|
||||
|
||||
assertEquals( NUMBER_OF_EMPLOYEES, employees.size() );
|
||||
for ( int i = 0 ; i < NUMBER_OF_EMPLOYEES ; i++ ) {
|
||||
if ( i == 1 || i == 7 ) {
|
||||
assertNull( employees.get( i ).task );
|
||||
}
|
||||
else {
|
||||
assertEquals( tasks.get( i ).id, employees.get( i ).task.id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMostNotFoundFromQuery() {
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
// delete all but last Task entity
|
||||
for ( int i = 0; i < 7; i++ ) {
|
||||
session.delete( tasks.get( i ) );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
statementInspector.clear();
|
||||
|
||||
final List<Employee> employees = doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
List<Employee> results =
|
||||
session.createQuery( "from Employee e order by e.id", Employee.class ).getResultList();
|
||||
for ( int i = 0 ; i < tasks.size() ; i++ ) {
|
||||
checkInBatchFetchQueue( tasks.get( i ).id, session, false );
|
||||
}
|
||||
return results;
|
||||
}
|
||||
);
|
||||
|
||||
final List<Integer> paramterCounts = statementInspector.parameterCounts;
|
||||
|
||||
// there should be 8 SQL statements executed
|
||||
assertEquals( 8, paramterCounts.size() );
|
||||
|
||||
// query loading Employee entities shouldn't have any parameters
|
||||
assertEquals( 0, paramterCounts.get( 0 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 0 will result in 1st batch;
|
||||
// query should have 5 parameters for [0,1,2,3,4];
|
||||
// Task with IDs == [0,1,2,3,4] won't be found
|
||||
assertEquals( 5, paramterCounts.get( 1 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 1 will result in 2nd batch;
|
||||
// query should have 4 parameters [1,5,6,7];
|
||||
// Task with IDs == [1,5,6] won't be found; Task with ID == 7 will be found.
|
||||
assertEquals( 4, paramterCounts.get( 2 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 2 will result in just querying
|
||||
// Task with ID == 2 (because the batch is empty).
|
||||
// query should have 1 parameter [2];
|
||||
// Task with ID == 2 won't be found.
|
||||
assertEquals( 1, paramterCounts.get( 3 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 3 will result in just querying
|
||||
// Task with ID == 3 (because the batch is empty).
|
||||
// query should have 1 parameter [3];
|
||||
// Task with ID == 3 won't be found.
|
||||
assertEquals( 1, paramterCounts.get( 4 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 4 will result in just querying
|
||||
// Task with ID == 4 (because the batch is empty).
|
||||
// query should have 1 parameter [4];
|
||||
// Task with ID == 4 won't be found.
|
||||
assertEquals( 1, paramterCounts.get( 5 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 5 will result in just querying
|
||||
// Task with ID == 5 (because the batch is empty).
|
||||
// query should have 1 parameter [5];
|
||||
// Task with ID == 5 won't be found.
|
||||
assertEquals( 1, paramterCounts.get( 6 ).intValue() );
|
||||
|
||||
// query specifically for Task with ID == 6 will result in just querying
|
||||
// Task with ID == 6 (because the batch is empty).
|
||||
// query should have 1 parameter [6];
|
||||
// Task with ID == 6 won't be found.
|
||||
assertEquals( 1, paramterCounts.get( 7 ).intValue() );
|
||||
|
||||
// no extra queries required to load entity with ID == 7 because it
|
||||
// was already loaded from 2nd batch
|
||||
|
||||
assertEquals( NUMBER_OF_EMPLOYEES, employees.size() );
|
||||
|
||||
for ( int i = 0 ; i < NUMBER_OF_EMPLOYEES ; i++ ) {
|
||||
if ( i == 7 ) {
|
||||
assertEquals( tasks.get( i ).id, employees.get( i ).task.id );
|
||||
}
|
||||
else {
|
||||
assertNull( employees.get( i ).task );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotFoundFromGet() {
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
// delete task so it is not found later when getting the Employee.
|
||||
session.delete( tasks.get( 0 ) );
|
||||
}
|
||||
);
|
||||
|
||||
statementInspector.clear();
|
||||
|
||||
doInHibernate(
|
||||
this::sessionFactory, session -> {
|
||||
Employee employee = session.get( Employee.class, "employee00" );
|
||||
checkInBatchFetchQueue( tasks.get( 0 ).id, session, false );
|
||||
assertNotNull( employee );
|
||||
assertNull( employee.task );
|
||||
}
|
||||
);
|
||||
|
||||
final List<Integer> paramterCounts = statementInspector.parameterCounts;
|
||||
|
||||
// there should be 2 SQL statements executed
|
||||
// 1) query to load Employee entity by ID (associated Tasks is registered for batch loading)
|
||||
// 2) batch will only contain the ID for the associated Task (which will not be found)
|
||||
assertEquals( 2, paramterCounts.size() );
|
||||
|
||||
// query loading Employee entities shouldn't have any parameters
|
||||
assertEquals( 1, paramterCounts.get( 0 ).intValue() );
|
||||
|
||||
// Will result in just querying a single Task (because the batch is empty).
|
||||
// query should have 1 parameter;
|
||||
// Task won't be found.
|
||||
assertEquals( 1, paramterCounts.get( 1 ).intValue() );
|
||||
}
|
||||
|
||||
private static void checkInBatchFetchQueue(long id, Session session, boolean expected) {
|
||||
final SessionImplementor sessionImplementor = (SessionImplementor) session;
|
||||
final EntityPersister persister =
|
||||
sessionImplementor.getFactory().getMetamodel().entityPersister( Task.class );
|
||||
final BatchFetchQueue batchFetchQueue =
|
||||
sessionImplementor.getPersistenceContext().getBatchFetchQueue();
|
||||
assertEquals( expected, batchFetchQueue.containsEntityKey( new EntityKey( id, persister ) ) );
|
||||
}
|
||||
|
||||
@Entity(name = "Employee")
|
||||
public static class Employee {
|
||||
@Id
|
||||
private String name;
|
||||
|
||||
@OneToOne(optional = true)
|
||||
@JoinColumn(foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
|
||||
@NotFound(action = NotFoundAction.IGNORE)
|
||||
private Task task;
|
||||
|
||||
private Employee() {
|
||||
}
|
||||
|
||||
private Employee(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Task")
|
||||
@BatchSize(size = 5)
|
||||
public static class Task {
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
public Task() {
|
||||
}
|
||||
}
|
||||
|
||||
public static class AStatementInspector implements StatementInspector {
|
||||
private List<Integer> parameterCounts = new ArrayList<>();
|
||||
|
||||
public String inspect(String sql) {
|
||||
parameterCounts.add( countParameters( sql ) );
|
||||
return sql;
|
||||
}
|
||||
private void clear() {
|
||||
parameterCounts.clear();
|
||||
}
|
||||
private int countParameters(String sql) {
|
||||
int count = 0;
|
||||
int parameterIndex = sql.indexOf( '?' );
|
||||
while ( parameterIndex >= 0 ) {
|
||||
count++;
|
||||
parameterIndex = sql.indexOf( '?', parameterIndex + 1 );
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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.test.batchfetch;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class BatchFetchNotFoundIgnoreDynamicStyleTest extends BatchFetchNotFoundIgnoreDefaultStyleTest {
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
super.configure( configuration );
|
||||
configuration.getProperties().put( Environment.BATCH_FETCH_STYLE, BatchFetchStyle.DYNAMIC );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.test.batchfetch;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.loader.BatchFetchStyle;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class BatchFetchNotFoundIgnorePaddedStyleTest extends BatchFetchNotFoundIgnoreDefaultStyleTest {
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
super.configure( configuration );
|
||||
configuration.getProperties().put( Environment.BATCH_FETCH_STYLE, BatchFetchStyle.PADDED );
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue