HHH-16043 Correct single ID and init empty for batch collection loading
This commit is contained in:
parent
17506b7f80
commit
f9b169242a
|
@ -14,8 +14,10 @@ import org.hibernate.LockOptions;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
import org.hibernate.engine.spi.CollectionEntry;
|
||||||
import org.hibernate.engine.spi.CollectionKey;
|
import org.hibernate.engine.spi.CollectionKey;
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.SubselectFetch;
|
import org.hibernate.engine.spi.SubselectFetch;
|
||||||
|
@ -30,6 +32,7 @@ import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
import org.hibernate.sql.results.internal.ResultsHelper;
|
||||||
import org.hibernate.sql.results.internal.RowTransformerStandardImpl;
|
import org.hibernate.sql.results.internal.RowTransformerStandardImpl;
|
||||||
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
||||||
|
|
||||||
|
@ -97,7 +100,7 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
|
||||||
null,
|
null,
|
||||||
attributeMapping.getKeyDescriptor(),
|
attributeMapping.getKeyDescriptor(),
|
||||||
null,
|
null,
|
||||||
batchSize,
|
1,
|
||||||
session.getLoadQueryInfluencers(),
|
session.getLoadQueryInfluencers(),
|
||||||
LockOptions.NONE,
|
LockOptions.NONE,
|
||||||
jdbcParameters::add,
|
jdbcParameters::add,
|
||||||
|
@ -201,6 +204,11 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
|
||||||
ListResultsConsumer.UniqueSemantic.FILTER
|
ListResultsConsumer.UniqueSemantic.FILTER
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for ( int i = smallBatchStart; i < smallBatchStart + smallBatchLength; i++ ) {
|
||||||
|
// collections that were not initialized here should be empty
|
||||||
|
finishLoadingCollection( batchIds[i], session );
|
||||||
|
}
|
||||||
|
|
||||||
// prepare for the next round...
|
// prepare for the next round...
|
||||||
smallBatchStart += smallBatchLength;
|
smallBatchStart += smallBatchLength;
|
||||||
if ( smallBatchStart >= numberOfIds ) {
|
if ( smallBatchStart >= numberOfIds ) {
|
||||||
|
@ -211,4 +219,20 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void finishLoadingCollection(Object key, SharedSessionContractImplementor session) {
|
||||||
|
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||||
|
final CollectionKey collectionKey = new CollectionKey( attributeMapping.getCollectionDescriptor(), key );
|
||||||
|
final PersistentCollection<?> collection = persistenceContext.getCollection( collectionKey );
|
||||||
|
if ( !collection.wasInitialized() ) {
|
||||||
|
final CollectionEntry entry = persistenceContext.getCollectionEntry( collection );
|
||||||
|
collection.initializeEmptyCollection( entry.getLoadedPersister() );
|
||||||
|
ResultsHelper.finalizeCollectionLoading(
|
||||||
|
persistenceContext,
|
||||||
|
entry.getLoadedPersister(),
|
||||||
|
collection,
|
||||||
|
collectionKey,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@SessionFactory(useCollectingStatementInspector = true)
|
@SessionFactory(useCollectingStatementInspector = true)
|
||||||
@ServiceRegistry(settings = {
|
@ServiceRegistry(settings = @Setting(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "5"))
|
||||||
@Setting(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "5")
|
|
||||||
})
|
|
||||||
@JiraKey("HHH-16043")
|
@JiraKey("HHH-16043")
|
||||||
public class NestedLazyManyToOneTest {
|
public class NestedLazyManyToOneTest {
|
||||||
|
private static final String QUESTION_MARK = "\\?";
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public void prepareData(SessionFactoryScope scope) {
|
public void prepareData(SessionFactoryScope scope) {
|
||||||
final Entity1 entity1 = new Entity1();
|
final Entity1 entity1 = new Entity1();
|
||||||
|
@ -87,10 +87,9 @@ public class NestedLazyManyToOneTest {
|
||||||
scope.inTransaction( session -> {
|
scope.inTransaction( session -> {
|
||||||
Entity1 fromDb = session.find( Entity1.class, "0" );
|
Entity1 fromDb = session.find( Entity1.class, "0" );
|
||||||
Set<Entity2> children = fromDb.getChildren();
|
Set<Entity2> children = fromDb.getChildren();
|
||||||
|
|
||||||
assertEquals( 8, children.size() );
|
assertEquals( 8, children.size() );
|
||||||
statementInspector.assertExecutedCount( 2 );
|
statementInspector.assertExecutedCount( 2 ); // 1 for Entity1, 1 for Entity2
|
||||||
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 1, "\\?", 1 );
|
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 1, QUESTION_MARK, 1 );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +121,8 @@ public class NestedLazyManyToOneTest {
|
||||||
|
|
||||||
assertEquals( 8, entity1.getChildren().size() );
|
assertEquals( 8, entity1.getChildren().size() );
|
||||||
statementInspector.assertExecutedCount( 3 ); // 1 for Entity1, 1 for Entity2, 1 for Entity3
|
statementInspector.assertExecutedCount( 3 ); // 1 for Entity1, 1 for Entity2, 1 for Entity3
|
||||||
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 2, "\\?", 5 );
|
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 1, QUESTION_MARK, 1 );
|
||||||
|
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 2, QUESTION_MARK, 5 );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,8 +145,9 @@ public class NestedLazyManyToOneTest {
|
||||||
|
|
||||||
assertEquals( 8, entity1.getChildren().size() );
|
assertEquals( 8, entity1.getChildren().size() );
|
||||||
statementInspector.assertExecutedCount( 4 ); // 1 for Entity1, 1 for Entity2, 2 for Entity3
|
statementInspector.assertExecutedCount( 4 ); // 1 for Entity1, 1 for Entity2, 2 for Entity3
|
||||||
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 2, "\\?", 5 );
|
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 1, QUESTION_MARK, 1 );
|
||||||
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 3, "\\?", 3 );
|
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 2, QUESTION_MARK, 5 );
|
||||||
|
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 3, QUESTION_MARK, 3 );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue