Fix issue with fetch deep and hql join fetch recognition

This commit is contained in:
Andrea Boriero 2020-12-09 17:47:55 +01:00
parent 7d74f1c727
commit c10b4e0f2f
7 changed files with 73 additions and 83 deletions

View File

@ -24,4 +24,9 @@ default String getFetchableName() {
* of this association's foreign-key * of this association's foreign-key
*/ */
ModelPart getKeyTargetMatchPart(); ModelPart getKeyTargetMatchPart();
@Override
default boolean incrementFetchDepth(){
return true;
}
} }

View File

@ -61,4 +61,9 @@ default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappin
String getSeparateCollectionTable(); String getSeparateCollectionTable();
boolean isBidirectionalAttributeName(NavigablePath fetchablePath); boolean isBidirectionalAttributeName(NavigablePath fetchablePath);
@Override
default boolean incrementFetchDepth(){
return true;
}
} }

View File

@ -710,7 +710,7 @@ private void consumeAttributeJoin(SqmAttributeJoin<?,?> sqmJoin, TableGroup lhsT
final NavigablePath parentNavigablePath = sqmJoinNavigablePath.getParent(); final NavigablePath parentNavigablePath = sqmJoinNavigablePath.getParent();
if ( pathSource instanceof PluralPersistentAttribute ) { if ( pathSource instanceof PluralPersistentAttribute ) {
final ModelPart pluralPart = lhsTableGroup.getModelPart().findSubPart( final ModelPart pluralPart = lhsTableGroup.getModelPart().findSubPart(
sqmJoin.getReferencedPathSource().getPathName(), pathSource.getPathName(),
SqmMappingModelHelper.resolveExplicitTreatTarget( sqmJoin, this ) SqmMappingModelHelper.resolveExplicitTreatTarget( sqmJoin, this )
); );
@ -751,7 +751,7 @@ private void consumeAttributeJoin(SqmAttributeJoin<?,?> sqmJoin, TableGroup lhsT
lhsTableGroup.addTableGroupJoin( joinedTableGroupJoin ); lhsTableGroup.addTableGroupJoin( joinedTableGroupJoin );
fromClauseIndex.register( sqmJoin, joinedTableGroup, elementPath ); fromClauseIndex.register( sqmJoin, joinedTableGroup, elementPath );
fromClauseIndex.registerTableGroup( elementPath, joinedTableGroup ); // fromClauseIndex.registerTableGroup( elementPath, joinedTableGroup );
} }
else if ( pathSource instanceof EmbeddedSqmPathSource ) { else if ( pathSource instanceof EmbeddedSqmPathSource ) {
final ModelPart joinedPart = lhsTableGroup.getModelPart().findSubPart( final ModelPart joinedPart = lhsTableGroup.getModelPart().findSubPart(
@ -803,8 +803,27 @@ else if ( pathSource instanceof EmbeddedSqmPathSource ) {
joinedPath = parentNavigablePath.append( sqmJoin.getAttribute().getName() ); joinedPath = parentNavigablePath.append( sqmJoin.getAttribute().getName() );
} }
NavigablePath elementPath;
if ( parentNavigablePath == null ) {
elementPath = sqmJoinNavigablePath;
pluralPersisterElementNavigablePathByFullPath.put(
sqmJoin.getNavigablePath().getFullPath(),
elementPath
);
}
else {
final NavigablePath elementNavigablePath = pluralPersisterElementNavigablePathByFullPath.get(
parentNavigablePath.getFullPath() );
if ( elementNavigablePath == null ) {
elementPath = sqmJoinNavigablePath;
}
else {
elementPath = elementNavigablePath.append( joinedPart.getPartName() );
}
}
joinedTableGroupJoin = ( (TableGroupJoinProducer) joinedPart ).createTableGroupJoin( joinedTableGroupJoin = ( (TableGroupJoinProducer) joinedPart ).createTableGroupJoin(
joinedPath, elementPath,
lhsTableGroup, lhsTableGroup,
sqmJoin.getExplicitAlias(), sqmJoin.getExplicitAlias(),
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(), sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
@ -816,7 +835,7 @@ else if ( pathSource instanceof EmbeddedSqmPathSource ) {
lhsTableGroup.addTableGroupJoin( joinedTableGroupJoin ); lhsTableGroup.addTableGroupJoin( joinedTableGroupJoin );
fromClauseIndex.register( sqmJoin, joinedTableGroup ); fromClauseIndex.register( sqmJoin, joinedTableGroup,elementPath );
} }
// add any additional join restrictions // add any additional join restrictions

View File

@ -43,6 +43,9 @@ public void register(SqmPath<?> sqmPath, TableGroup tableGroup) {
public void register(SqmPath<?> sqmPath, TableGroup tableGroup, NavigablePath identifierForTableGroup) { public void register(SqmPath<?> sqmPath, TableGroup tableGroup, NavigablePath identifierForTableGroup) {
registerTableGroup( sqmPath.getNavigablePath(), tableGroup ); registerTableGroup( sqmPath.getNavigablePath(), tableGroup );
if ( identifierForTableGroup != null ) {
registerTableGroup( identifierForTableGroup, tableGroup );
}
if ( sqmPath.getExplicitAlias() != null ) { if ( sqmPath.getExplicitAlias() != null ) {
final TableGroup previousAliasReg = tableGroupByAliasXref.put( sqmPath.getExplicitAlias(), tableGroup ); final TableGroup previousAliasReg = tableGroupByAliasXref.put( sqmPath.getExplicitAlias(), tableGroup );
@ -67,11 +70,13 @@ private void registerJoinFetch(SqmAttributeJoin sqmJoin, NavigablePath identifie
if ( fetchesByPath == null ) { if ( fetchesByPath == null ) {
fetchesByPath = new HashMap<>(); fetchesByPath = new HashMap<>();
} }
NavigablePath navigablePath = sqmJoin.getNavigablePath();
fetchesByPath.put( navigablePath.getIdentifierForTableGroup(), sqmJoin );
if ( identifierForTableGroup != null ) { if ( identifierForTableGroup != null ) {
fetchesByPath.put( identifierForTableGroup.getIdentifierForTableGroup(), sqmJoin ); fetchesByPath.put( identifierForTableGroup.getIdentifierForTableGroup(), sqmJoin );
} }
else {
final NavigablePath navigablePath = sqmJoin.getNavigablePath();
fetchesByPath.put( navigablePath.getIdentifierForTableGroup(), sqmJoin );
}
} }
public boolean isResolved(SqmFrom fromElement) { public boolean isResolved(SqmFrom fromElement) {

View File

@ -289,8 +289,11 @@ public List<Fetch> visitFetches(FetchParent fetchParent) {
return; return;
} }
final boolean incrementFetchDepth = fetchable.incrementFetchDepth();
try { try {
fetchDepth++; if ( incrementFetchDepth ) {
fetchDepth++;
}
final Fetch fetch = buildFetch( fetchablePath, fetchParent, fetchable, isKeyFetchable ); final Fetch fetch = buildFetch( fetchablePath, fetchParent, fetchable, isKeyFetchable );
if ( fetch != null ) { if ( fetch != null ) {
@ -308,7 +311,9 @@ public List<Fetch> visitFetches(FetchParent fetchParent) {
} }
} }
finally { finally {
fetchDepth--; if ( incrementFetchDepth ) {
fetchDepth--;
}
} }
}; };
@ -398,12 +403,9 @@ else if ( getLoadQueryInfluencers().hasEnabledFetchProfiles() ) {
// lastly, account for any app-defined max-fetch-depth // lastly, account for any app-defined max-fetch-depth
final Integer maxDepth = getCreationContext().getMaximumFetchDepth(); final Integer maxDepth = getCreationContext().getMaximumFetchDepth();
if ( maxDepth != null ) { if ( maxDepth != null ) {
if ( fetchDepth == maxDepth ) { if ( fetchDepth >= maxDepth ) {
joined = false; joined = false;
} }
else if ( fetchDepth > maxDepth ) {
return null;
}
} }
if ( joined && fetchable instanceof TableGroupJoinProducer ) { if ( joined && fetchable instanceof TableGroupJoinProducer ) {

View File

@ -39,4 +39,8 @@ Fetch generateFetch(
LockMode lockMode, LockMode lockMode,
String resultVariable, String resultVariable,
DomainResultCreationState creationState); DomainResultCreationState creationState);
default boolean incrementFetchDepth(){
return false;
}
} }

View File

@ -17,6 +17,7 @@
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -37,17 +38,17 @@
@SessionFactory(statementInspectorClass = SQLStatementInspector.class) @SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class CompositeIdTest { public class CompositeIdTest {
// @AfterEach @AfterEach
// public void tearDown(SessionFactoryScope scope) { public void tearDown(SessionFactoryScope scope) {
// scope.inTransaction( scope.inTransaction(
// session -> { session -> {
// session.createQuery( "delete from LineItem" ).executeUpdate(); session.createQuery( "delete from LineItem" ).executeUpdate();
// session.createQuery( "delete from Order" ).executeUpdate(); session.createQuery( "delete from Order" ).executeUpdate();
// session.createQuery( "delete from Customer" ).executeUpdate(); session.createQuery( "delete from Customer" ).executeUpdate();
// session.createQuery( "delete from Product" ).executeUpdate(); session.createQuery( "delete from Product" ).executeUpdate();
// } }
// ); );
// } }
@Test @Test
public void testQuery(SessionFactoryScope scope) { public void testQuery(SessionFactoryScope scope) {
@ -185,62 +186,6 @@ public void testCompositeIds(SessionFactoryScope scope) {
); );
} }
@Test
public void testNonLazyFetch_2(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Product p = new Product();
p.setProductId( "A123" );
p.setDescription( "nipple ring" );
p.setPrice( new BigDecimal( 1.0 ) );
p.setNumberAvailable( 1004 );
session.persist( p );
Product p2 = new Product();
p2.setProductId( "X525" );
p2.setDescription( "nose stud" );
p2.setPrice( new BigDecimal( 3.0 ) );
p2.setNumberAvailable( 105 );
session.persist( p2 );
Customer c = new Customer();
c.setAddress( "St Kilda Rd, MEL, 3000" );
c.setName( "Virginia" );
c.setCustomerId( "C111" );
session.persist( c );
Order o = new Order( c );
o.setOrderDate( Calendar.getInstance() );
LineItem li = new LineItem( o, p );
li.setQuantity( 2 );
}
);
scope.inTransaction(
session -> {
Order o = (Order) session.createQuery(
"from Order o left join fetch o.lineItems li left join fetch li.product p" )
.uniqueResult();
assertTrue( Hibernate.isInitialized( o.getLineItems() ) );
LineItem li = (LineItem) o.getLineItems().iterator().next();
assertTrue( Hibernate.isInitialized( li ) );
assertTrue( Hibernate.isInitialized( li.getProduct() ) );
}
);
// scope.inTransaction(
// session -> {
// Order o = (Order) session.createQuery( "from Order o" ).uniqueResult();
// assertTrue( Hibernate.isInitialized( o.getLineItems() ) );
// LineItem li = (LineItem) o.getLineItems().iterator().next();
// assertTrue( Hibernate.isInitialized( li ) );
// assertFalse( Hibernate.isInitialized( li.getProduct() ) );
// }
// );
}
@Test @Test
public void testNonLazyFetch(SessionFactoryScope scope) { public void testNonLazyFetch(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
@ -350,10 +295,15 @@ public void testMultipleCollectionFetch(SessionFactoryScope scope) {
.uniqueResult(); .uniqueResult();
assertTrue( Hibernate.isInitialized( c.getOrders() ) ); assertTrue( Hibernate.isInitialized( c.getOrders() ) );
assertEquals( c.getOrders().size(), 2 ); assertEquals( c.getOrders().size(), 2 );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get( 0 ) ).getLineItems() ) );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get( 1 ) ).getLineItems() ) ); Order o1 = (Order) c.getOrders().get( 0 );
assertEquals( 2, ( (Order) c.getOrders().get( 0 ) ).getLineItems().size() ); assertTrue( Hibernate.isInitialized( o1.getLineItems() ) );
assertEquals( 2, ( (Order) c.getOrders().get( 1 ) ).getLineItems().size() );
Order o2 = (Order) c.getOrders().get( 1 );
assertTrue( Hibernate.isInitialized( o2.getLineItems() ) );
assertEquals( 2, o1.getLineItems().size() );
assertEquals( 2, o2.getLineItems().size() );
} }
); );
} }