Fix issue with fetch deep and hql join fetch recognition
This commit is contained in:
parent
7d74f1c727
commit
c10b4e0f2f
|
@ -24,4 +24,9 @@ public interface EntityAssociationMapping extends ModelPart, Association {
|
|||
* of this association's foreign-key
|
||||
*/
|
||||
ModelPart getKeyTargetMatchPart();
|
||||
|
||||
@Override
|
||||
default boolean incrementFetchDepth(){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,4 +61,9 @@ public interface PluralAttributeMapping
|
|||
String getSeparateCollectionTable();
|
||||
|
||||
boolean isBidirectionalAttributeName(NavigablePath fetchablePath);
|
||||
|
||||
@Override
|
||||
default boolean incrementFetchDepth(){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -289,8 +289,11 @@ public class StandardSqmSelectTranslator
|
|||
return;
|
||||
}
|
||||
|
||||
final boolean incrementFetchDepth = fetchable.incrementFetchDepth();
|
||||
try {
|
||||
fetchDepth++;
|
||||
if ( incrementFetchDepth ) {
|
||||
fetchDepth++;
|
||||
}
|
||||
final Fetch fetch = buildFetch( fetchablePath, fetchParent, fetchable, isKeyFetchable );
|
||||
|
||||
if ( fetch != null ) {
|
||||
|
@ -308,7 +311,9 @@ public class StandardSqmSelectTranslator
|
|||
}
|
||||
}
|
||||
finally {
|
||||
fetchDepth--;
|
||||
if ( incrementFetchDepth ) {
|
||||
fetchDepth--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 ) {
|
||||
|
|
|
@ -39,4 +39,8 @@ public interface Fetchable extends ModelPart {
|
|||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState);
|
||||
|
||||
default boolean incrementFetchDepth(){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue