Skip to content

Commit 4defc8a

Browse files
gbadnersebersole
authored andcommitted
HHH-8276 - Integrate LoadPlans into UniqueEntityLoader (PoC)
1 parent 438dd9c commit 4defc8a

37 files changed

+470
-130
lines changed

hibernate-core/src/main/java/org/hibernate/loader/plan/internal/SingleRootReturnLoadPlanBuilderStrategy.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@
3636
import org.hibernate.loader.plan.spi.CollectionReturn;
3737
import org.hibernate.loader.plan.spi.EntityReturn;
3838
import org.hibernate.loader.plan.spi.LoadPlan;
39-
import org.hibernate.loader.plan.spi.build.LoadPlanBuilderStrategy;
4039
import org.hibernate.loader.plan.spi.Return;
40+
import org.hibernate.loader.plan2.spi.FetchSource;
4141
import org.hibernate.persister.collection.CollectionPersister;
4242
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
43+
import org.hibernate.persister.walking.spi.AssociationKey;
4344
import org.hibernate.persister.walking.spi.CollectionDefinition;
4445
import org.hibernate.persister.walking.spi.EntityDefinition;
4546

@@ -152,4 +153,9 @@ protected CollectionReturn buildRootCollectionReturn(CollectionDefinition collec
152153
StringHelper.unqualify( collectionRole )
153154
);
154155
}
156+
157+
@Override
158+
public FetchSource registeredFetchSource(AssociationKey associationKey) {
159+
return null;
160+
}
155161
}

hibernate-core/src/main/java/org/hibernate/loader/plan/spi/build/AbstractLoadPlanBuilderStrategy.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import org.hibernate.loader.plan.spi.CollectionFetch;
4545
import org.hibernate.loader.plan.spi.CollectionReference;
4646
import org.hibernate.loader.plan.spi.CollectionReturn;
47-
import org.hibernate.loader.plan.spi.CompositeElementGraph;
4847
import org.hibernate.loader.plan.spi.CompositeFetch;
4948
import org.hibernate.loader.plan.spi.CopyContext;
5049
import org.hibernate.loader.plan.spi.EntityFetch;
@@ -67,7 +66,6 @@
6766
import org.hibernate.persister.walking.spi.CollectionDefinition;
6867
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
6968
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
70-
import org.hibernate.persister.walking.spi.CompositeCollectionElementDefinition;
7169
import org.hibernate.persister.walking.spi.CompositionDefinition;
7270
import org.hibernate.persister.walking.spi.EntityDefinition;
7371
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
@@ -427,8 +425,9 @@ public void associationKeyRegistered(AssociationKey associationKey) {
427425
}
428426

429427
@Override
430-
public void foundCircularAssociationKey(AssociationKey associationKey, AttributeDefinition attributeDefinition) {
428+
public void foundCircularAssociation(AssociationAttributeDefinition attributeDefinition) {
431429
// todo : use this information to create the BiDirectionalEntityFetch instances
430+
final AssociationKey associationKey = attributeDefinition.getAssociationKey();
432431
final FetchOwner fetchOwner = fetchedAssociationKeyOwnerMap.get( associationKey );
433432
if ( fetchOwner == null ) {
434433
throw new IllegalStateException(

hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/FetchStyleLoadPlanBuildingAssociationVisitationStrategy.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@
3434
import org.hibernate.internal.CoreLogging;
3535
import org.hibernate.loader.PropertyPath;
3636
import org.hibernate.loader.plan2.build.spi.AbstractLoadPlanBuildingAssociationVisitationStrategy;
37-
import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingAssociationVisitationStrategy;
37+
import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource;
38+
import org.hibernate.loader.plan2.spi.CollectionFetch;
3839
import org.hibernate.loader.plan2.spi.CollectionReturn;
40+
import org.hibernate.loader.plan2.spi.EntityFetch;
3941
import org.hibernate.loader.plan2.spi.EntityReturn;
4042
import org.hibernate.loader.plan2.spi.LoadPlan;
4143
import org.hibernate.loader.plan2.spi.Return;
4244
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
4345
import org.hibernate.persister.walking.spi.AssociationKey;
44-
import org.hibernate.persister.walking.spi.AttributeDefinition;
4546

4647
/**
4748
* LoadPlanBuilderStrategy implementation used for building LoadPlans based on metamodel-defined fetching. Built
@@ -129,11 +130,6 @@ protected boolean isTooManyCollections() {
129130
return false;
130131
}
131132

132-
@Override
133-
public void foundCircularAssociationKey(AssociationKey associationKey, AttributeDefinition attributeDefinition) {
134-
// todo : implement this
135-
}
136-
137133
// @Override
138134
// protected EntityReturn buildRootEntityReturn(EntityDefinition entityDefinition) {
139135
// final String entityName = entityDefinition.getEntityPersister().getEntityName();

hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeEntityIdentifierDescription.java

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,25 @@
2323
*/
2424
package org.hibernate.loader.plan2.build.internal.returns;
2525

26+
import org.hibernate.engine.FetchStrategy;
2627
import org.hibernate.loader.PropertyPath;
2728
import org.hibernate.loader.plan2.build.spi.ExpandingEntityIdentifierDescription;
29+
import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext;
2830
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
29-
import org.hibernate.loader.plan2.spi.EntityIdentifierDescription;
31+
import org.hibernate.loader.plan2.spi.EntityFetch;
3032
import org.hibernate.loader.plan2.spi.EntityReference;
3133
import org.hibernate.loader.plan2.spi.FetchSource;
34+
import org.hibernate.loader.plan2.spi.Join;
35+
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
3236
import org.hibernate.type.CompositeType;
3337

3438
/**
3539
* @author Steve Ebersole
40+
* @author Gail Badner
3641
*/
3742
public abstract class AbstractCompositeEntityIdentifierDescription
3843
extends AbstractCompositeFetch
39-
implements EntityIdentifierDescription, FetchSource, ExpandingEntityIdentifierDescription {
44+
implements FetchSource, ExpandingEntityIdentifierDescription {
4045

4146
private final EntityReference entityReference;
4247

@@ -57,6 +62,55 @@ public boolean hasFetches() {
5762
@Override
5863
public FetchSource getSource() {
5964
// the source for this (as a Fetch) is the entity reference
60-
return (FetchSource) entityReference.getIdentifierDescription();
65+
return entityReference;
66+
}
67+
68+
@Override
69+
protected EntityFetch createEntityFetch(
70+
AssociationAttributeDefinition attributeDefinition,
71+
FetchStrategy fetchStrategy,
72+
Join fetchedJoin,
73+
LoadPlanBuildingContext loadPlanBuildingContext) {
74+
// we have a key-many-to-one
75+
//
76+
// IMPL NOTE: we pass ourselves as the ExpandingFetchSource to collect fetches and later build
77+
// the IdentifierDescription
78+
79+
// if `this` is a fetch and its owner is "the same" (bi-directionality) as the attribute to be join fetched
80+
// we should wrap our FetchSource as an EntityFetch. That should solve everything except for the alias
81+
// context lookups because of the different instances (because of wrapping). So somehow the consumer of this
82+
// needs to be able to unwrap it to do the alias lookup, and would have to know to do that.
83+
//
84+
//
85+
// we are processing the EntityReference(Address) identifier. we come across its key-many-to-one reference
86+
// to Person. Now, if EntityReference(Address) is an instance of EntityFetch(Address) there is a strong
87+
// likelihood that we have a bi-directionality and need to handle that specially.
88+
//
89+
// how to best (a) find the bi-directionality and (b) represent that?
90+
91+
final FetchSource registeredFetchSource = loadPlanBuildingContext.registeredFetchSource(
92+
attributeDefinition.getAssociationKey()
93+
);
94+
if ( isKeyManyToOneBidirectionalAttributeDefinition( attributeDefinition, loadPlanBuildingContext ) ) {
95+
return new KeyManyToOneBidirectionalEntityFetchImpl(
96+
this,
97+
attributeDefinition,
98+
fetchStrategy,
99+
fetchedJoin,
100+
registeredFetchSource.resolveEntityReference()
101+
);
102+
}
103+
else {
104+
return super.createEntityFetch( attributeDefinition, fetchStrategy, fetchedJoin, loadPlanBuildingContext );
105+
}
106+
}
107+
108+
private boolean isKeyManyToOneBidirectionalAttributeDefinition(
109+
AssociationAttributeDefinition attributeDefinition,
110+
LoadPlanBuildingContext loadPlanBuildingContext) {
111+
final FetchSource registeredFetchSource = loadPlanBuildingContext.registeredFetchSource(
112+
attributeDefinition.getAssociationKey()
113+
);
114+
return registeredFetchSource != null && registeredFetchSource != getSource();
61115
}
62116
}

hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeFetch.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737
import org.hibernate.loader.plan2.spi.CompositeFetch;
3838
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
3939
import org.hibernate.loader.plan2.spi.EntityFetch;
40+
import org.hibernate.loader.plan2.spi.EntityReference;
4041
import org.hibernate.loader.plan2.spi.Fetch;
42+
import org.hibernate.loader.plan2.spi.FetchSource;
4143
import org.hibernate.loader.plan2.spi.Join;
4244
import org.hibernate.persister.collection.CollectionPersister;
4345
import org.hibernate.persister.entity.EntityPersister;
@@ -52,6 +54,7 @@
5254

5355
/**
5456
* @author Steve Ebersole
57+
* @author Gail Badner
5558
*/
5659
public abstract class AbstractCompositeFetch implements CompositeFetch, ExpandingFetchSource {
5760
private static final FetchStrategy FETCH_STRATEGY = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
@@ -78,6 +81,30 @@ protected CompositeQuerySpace resolveCompositeQuerySpace(LoadPlanBuildingContext
7881
return compositeQuerySpace;
7982
}
8083

84+
@Override
85+
public EntityReference resolveEntityReference() {
86+
return resolveFetchSourceEntityReference( this );
87+
}
88+
89+
private static EntityReference resolveFetchSourceEntityReference(CompositeFetch fetch) {
90+
final FetchSource fetchSource = fetch.getSource();
91+
92+
if ( EntityReference.class.isInstance( fetchSource ) ) {
93+
return (EntityReference) fetchSource;
94+
}
95+
else if ( CompositeFetch.class.isInstance( fetchSource ) ) {
96+
return resolveFetchSourceEntityReference( (CompositeFetch) fetchSource );
97+
}
98+
throw new IllegalStateException(
99+
String.format(
100+
"Cannot resolve FetchOwner [%s] of Fetch [%s (%s)] to an EntityReference",
101+
fetchSource,
102+
fetch,
103+
fetch.getPropertyPath()
104+
)
105+
);
106+
}
107+
81108
@Override
82109
public String getQuerySpaceUid() {
83110
return compositeQuerySpace.getUid();
@@ -117,14 +144,23 @@ public EntityFetch buildEntityFetch(
117144
loadPlanBuildingContext.getQuerySpaces().generateImplicitUid(),
118145
attributeDefinition.isNullable()
119146
);
120-
final EntityFetch fetch = new EntityFetchImpl(
147+
final EntityFetch fetch = createEntityFetch( attributeDefinition, fetchStrategy, join, loadPlanBuildingContext );
148+
addFetch( fetch );
149+
return fetch;
150+
}
151+
152+
protected EntityFetch createEntityFetch(
153+
AssociationAttributeDefinition attributeDefinition,
154+
FetchStrategy fetchStrategy,
155+
Join fetchedJoin,
156+
LoadPlanBuildingContext loadPlanBuildingContext) {
157+
return new EntityFetchImpl(
121158
this,
122159
attributeDefinition,
123160
fetchStrategy,
124-
join
161+
fetchedJoin
125162
);
126-
addFetch( fetch );
127-
return fetch;
163+
128164
}
129165

130166
private void addFetch(Fetch fetch) {

hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractEntityReference.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ private EncapsulatedEntityIdentifierDescription buildEncapsulatedCompositeIdenti
116116
);
117117
}
118118

119+
@Override
120+
public EntityReference resolveEntityReference() {
121+
return this;
122+
}
123+
119124
protected EntityQuerySpace getEntityQuerySpace() {
120125
return entityQuerySpace;
121126
}

hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionReturnImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
package org.hibernate.loader.plan2.build.internal.returns;
2525

2626
import org.hibernate.loader.PropertyPath;
27+
import org.hibernate.loader.plan2.build.internal.spaces.CollectionQuerySpaceImpl;
2728
import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext;
2829
import org.hibernate.loader.plan2.spi.CollectionReturn;
2930
import org.hibernate.persister.walking.spi.CollectionDefinition;
@@ -35,7 +36,7 @@ public class CollectionReturnImpl extends AbstractCollectionReference implements
3536

3637
public CollectionReturnImpl(CollectionDefinition collectionDefinition, LoadPlanBuildingContext context) {
3738
super(
38-
context.getQuerySpaces().makeCollectionQuerySpace(
39+
(CollectionQuerySpaceImpl) context.getQuerySpaces().makeCollectionQuerySpace(
3940
context.getQuerySpaces().generateImplicitUid(),
4041
collectionDefinition.getCollectionPersister()
4142
),

hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EncapsulatedEntityIdentifierDescription.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,5 @@ protected EncapsulatedEntityIdentifierDescription(
5454
PropertyPath propertyPath) {
5555
super( entityReference, compositeQuerySpace, compositeType, propertyPath );
5656
}
57+
5758
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
package org.hibernate.loader.plan2.build.internal.returns;
25+
26+
import org.hibernate.engine.FetchStrategy;
27+
import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource;
28+
import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch;
29+
import org.hibernate.loader.plan2.spi.EntityReference;
30+
import org.hibernate.loader.plan2.spi.Join;
31+
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
32+
33+
/**
34+
* Represents a key-many-to-one fetch that is bi-directionally join fetched.
35+
* <p/>
36+
* For example, consider an Order entity whose primary key is partially made up of the Customer entity to which
37+
* it is associated. When we join fetch Customer -> Order(s) and then Order -> Customer we have a bi-directional
38+
* fetch. This class would be used to represent the Order -> Customer part of that link.
39+
*
40+
* @author Steve Ebersole
41+
*/
42+
public class KeyManyToOneBidirectionalEntityFetchImpl extends EntityFetchImpl implements BidirectionalEntityFetch {
43+
private final EntityReference targetEntityReference;
44+
45+
public KeyManyToOneBidirectionalEntityFetchImpl(
46+
ExpandingFetchSource fetchSource,
47+
AssociationAttributeDefinition fetchedAttribute,
48+
FetchStrategy fetchStrategy,
49+
Join fetchedJoin,
50+
EntityReference targetEntityReference) {
51+
super( fetchSource, fetchedAttribute, fetchStrategy, fetchedJoin );
52+
this.targetEntityReference = targetEntityReference;
53+
}
54+
55+
public EntityReference getTargetEntityReference() {
56+
return targetEntityReference;
57+
}
58+
}

hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/CollectionQuerySpaceImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.hibernate.loader.plan2.spi.CollectionQuerySpace;
3030
import org.hibernate.loader.plan2.spi.Join;
3131
import org.hibernate.persister.collection.CollectionPersister;
32-
import org.hibernate.persister.collection.QueryableCollection;
3332
import org.hibernate.persister.entity.EntityPersister;
3433
import org.hibernate.persister.entity.PropertyMapping;
3534
import org.hibernate.persister.entity.Queryable;

0 commit comments

Comments
 (0)