JPA Criteria do not load eagerly JOIN Fecth collections as Hibernate Criteria did

This commit is contained in:
Andrea Boriero 2021-04-06 17:14:55 +02:00
parent f6f1cb06d4
commit dc21d565d3
4 changed files with 34 additions and 7 deletions

View File

@ -510,6 +510,14 @@ public class PluralAttributeMappingImpl
);
}
else {
if ( collectionDescriptor.isLazy() ) {
return createDelayedCollectionFetch(
fetchParent,
fetchablePath,
creationState,
sqlAstCreationState
);
}
return new SelectEagerCollectionFetch( fetchablePath, this, fetchParent );
}
}
@ -518,11 +526,17 @@ public class PluralAttributeMappingImpl
return new SelectEagerCollectionFetch( fetchablePath, this, fetchParent );
}
final FromClauseAccess fromClauseAccess = sqlAstCreationState.getFromClauseAccess();
final TableGroup fetchParentTableGroup = fromClauseAccess.getTableGroup( fetchParent.getNavigablePath() );
return createDelayedCollectionFetch( fetchParent, fetchablePath, creationState, sqlAstCreationState );
}
private DelayedCollectionFetch createDelayedCollectionFetch(
FetchParent fetchParent,
NavigablePath fetchablePath,
DomainResultCreationState creationState,
SqlAstCreationState sqlAstCreationState) {
final DomainResult fkResult = getKeyDescriptor().createDomainResult(
fetchablePath,
fetchParentTableGroup,
sqlAstCreationState.getFromClauseAccess().getTableGroup( fetchParent.getNavigablePath() ),
false,
creationState
);

View File

@ -29,6 +29,7 @@ import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.jdbc.spi.JdbcValues;
import org.hibernate.sql.results.spi.RowReader;
import org.hibernate.sql.results.spi.RowTransformer;
import org.hibernate.stat.spi.StatisticsImplementor;
/**
* @author Steve Ebersole
@ -114,6 +115,11 @@ public class ResultsHelper {
final BatchFetchQueue batchFetchQueue = persistenceContext.getBatchFetchQueue();
batchFetchQueue.removeBatchLoadableCollection( collectionEntry );
final StatisticsImplementor statistics = persistenceContext.getSession().getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.loadCollection( collectionDescriptor.getRole() );
}
// todo (6.0) : there is other logic still needing to be implemented here. caching, etc
// see org.hibernate.engine.loading.internal.CollectionLoadContext#endLoadingCollection in 5.x
}

View File

@ -144,7 +144,7 @@ public class CollectionTest {
scope.inTransaction(
s -> {
User u2 = findUser( s );
assertTrue( Hibernate.isInitialized( u2.getEmailAddresses() ) );
assertFalse( Hibernate.isInitialized( u2.getEmailAddresses() ) );
assertFalse( Hibernate.isInitialized( u2.getPermissions() ) );
assertEquals( 2, u2.getEmailAddresses().size() );
s.delete( u2 );

View File

@ -944,6 +944,7 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
public void testManyToManyBaseThruCriteria() {
inSession(
session -> {
sessionFactory().getStatistics().clear();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Product> criteria = criteriaBuilder.createQuery( Product.class );
Root<Product> root = criteria.from( Product.class );
@ -957,10 +958,16 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
Product prod = result.get( 0 );
long initLoadCount = sessionFactory().getStatistics().getCollectionLoadCount();
long initFetchCount = sessionFactory().getStatistics().getCollectionFetchCount();
// should already have been initialized...
// categories should not have been initialized...
assertTrue(
"load with join fetch of many-to-many triggers join fetch",
( 0 == initLoadCount ) && ( 0 == initFetchCount )
);
int size = prod.getCategories().size();
assertEquals( "Incorrect non-filtered collection count", 2, size );
@ -968,8 +975,8 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
long currFetchCount = sessionFactory().getStatistics().getCollectionFetchCount();
assertTrue(
"load with join fetch of many-to-many did not trigger join fetch",
( initLoadCount == currLoadCount ) && ( initFetchCount == currFetchCount )
"load with join fetch of many-to-many triggers join fetch",
( 1 == currLoadCount ) && ( 1 == currFetchCount )
);
// make sure we did not get back a collection of proxies