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 @@ public interface EntityAssociationMapping extends ModelPart, Association {
* of this association's foreign-key
*/
ModelPart getKeyTargetMatchPart();
@Override
default boolean incrementFetchDepth(){
return true;
}
}

View File

@ -61,4 +61,9 @@ public interface PluralAttributeMapping
String getSeparateCollectionTable();
boolean isBidirectionalAttributeName(NavigablePath fetchablePath);
@Override
default boolean incrementFetchDepth(){
return true;
}
}

View File

@ -710,7 +710,7 @@ public abstract class BaseSqmToSqlAstConverter
final NavigablePath parentNavigablePath = sqmJoinNavigablePath.getParent();
if ( pathSource instanceof PluralPersistentAttribute ) {
final ModelPart pluralPart = lhsTableGroup.getModelPart().findSubPart(
sqmJoin.getReferencedPathSource().getPathName(),
pathSource.getPathName(),
SqmMappingModelHelper.resolveExplicitTreatTarget( sqmJoin, this )
);
@ -751,7 +751,7 @@ public abstract class BaseSqmToSqlAstConverter
lhsTableGroup.addTableGroupJoin( joinedTableGroupJoin );
fromClauseIndex.register( sqmJoin, joinedTableGroup, elementPath );
fromClauseIndex.registerTableGroup( elementPath, joinedTableGroup );
// fromClauseIndex.registerTableGroup( elementPath, joinedTableGroup );
}
else if ( pathSource instanceof EmbeddedSqmPathSource ) {
final ModelPart joinedPart = lhsTableGroup.getModelPart().findSubPart(
@ -803,8 +803,27 @@ public abstract class BaseSqmToSqlAstConverter
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(
joinedPath,
elementPath,
lhsTableGroup,
sqmJoin.getExplicitAlias(),
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
@ -816,7 +835,7 @@ public abstract class BaseSqmToSqlAstConverter
lhsTableGroup.addTableGroupJoin( joinedTableGroupJoin );
fromClauseIndex.register( sqmJoin, joinedTableGroup );
fromClauseIndex.register( sqmJoin, joinedTableGroup,elementPath );
}
// add any additional join restrictions

View File

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

View File

@ -289,8 +289,11 @@ public class StandardSqmSelectTranslator
return;
}
final boolean incrementFetchDepth = fetchable.incrementFetchDepth();
try {
if ( incrementFetchDepth ) {
fetchDepth++;
}
final Fetch fetch = buildFetch( fetchablePath, fetchParent, fetchable, isKeyFetchable );
if ( fetch != null ) {
@ -308,8 +311,10 @@ public class StandardSqmSelectTranslator
}
}
finally {
if ( incrementFetchDepth ) {
fetchDepth--;
}
}
};
// todo (6.0) : determine how to best handle TREAT
@ -398,12 +403,9 @@ public class StandardSqmSelectTranslator
// lastly, account for any app-defined max-fetch-depth
final Integer maxDepth = getCreationContext().getMaximumFetchDepth();
if ( maxDepth != null ) {
if ( fetchDepth == maxDepth ) {
if ( fetchDepth >= maxDepth ) {
joined = false;
}
else if ( fetchDepth > maxDepth ) {
return null;
}
}
if ( joined && fetchable instanceof TableGroupJoinProducer ) {

View File

@ -39,4 +39,8 @@ public interface Fetchable extends ModelPart {
LockMode lockMode,
String resultVariable,
DomainResultCreationState creationState);
default boolean incrementFetchDepth(){
return false;
}
}

View File

@ -17,6 +17,7 @@ import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -37,17 +38,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class CompositeIdTest {
// @AfterEach
// public void tearDown(SessionFactoryScope scope) {
// scope.inTransaction(
// session -> {
// session.createQuery( "delete from LineItem" ).executeUpdate();
// session.createQuery( "delete from Order" ).executeUpdate();
// session.createQuery( "delete from Customer" ).executeUpdate();
// session.createQuery( "delete from Product" ).executeUpdate();
// }
// );
// }
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from LineItem" ).executeUpdate();
session.createQuery( "delete from Order" ).executeUpdate();
session.createQuery( "delete from Customer" ).executeUpdate();
session.createQuery( "delete from Product" ).executeUpdate();
}
);
}
@Test
public void testQuery(SessionFactoryScope scope) {
@ -185,62 +186,6 @@ public class CompositeIdTest {
);
}
@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
public void testNonLazyFetch(SessionFactoryScope scope) {
scope.inTransaction(
@ -350,10 +295,15 @@ public class CompositeIdTest {
.uniqueResult();
assertTrue( Hibernate.isInitialized( c.getOrders() ) );
assertEquals( c.getOrders().size(), 2 );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get( 0 ) ).getLineItems() ) );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get( 1 ) ).getLineItems() ) );
assertEquals( 2, ( (Order) c.getOrders().get( 0 ) ).getLineItems().size() );
assertEquals( 2, ( (Order) c.getOrders().get( 1 ) ).getLineItems().size() );
Order o1 = (Order) c.getOrders().get( 0 );
assertTrue( Hibernate.isInitialized( o1.getLineItems() ) );
Order o2 = (Order) c.getOrders().get( 1 );
assertTrue( Hibernate.isInitialized( o2.getLineItems() ) );
assertEquals( 2, o1.getLineItems().size() );
assertEquals( 2, o2.getLineItems().size() );
}
);
}