Skip to content

Commit d2597ea

Browse files
committed
HHH-18714 add support for inheritance in NamedEntityGraph annotation
1 parent 36d6e46 commit d2597ea

File tree

3 files changed

+549
-31
lines changed

3 files changed

+549
-31
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java

Lines changed: 92 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.io.Serializable;
1010
import java.lang.reflect.Field;
1111
import java.util.ArrayList;
12+
import java.util.Arrays;
1213
import java.util.Collection;
1314
import java.util.HashMap;
1415
import java.util.HashSet;
@@ -73,7 +74,6 @@
7374
import static org.hibernate.metamodel.internal.InjectionHelper.injectTypedQueryReference;
7475

7576
/**
76-
*
7777
* @author Steve Ebersole
7878
*/
7979
public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
@@ -106,7 +106,7 @@ private ImportInfo(String importedName, Class<T> loadedClass) {
106106
private final Map<Class<?>, String> entityProxyInterfaceMap = new HashMap<>();
107107

108108
private final Map<String, ImportInfo<?>> nameToImportMap = new ConcurrentHashMap<>();
109-
private final Map<String,Object> knownInvalidnameToImportMap = new ConcurrentHashMap<>();
109+
private final Map<String, Object> knownInvalidnameToImportMap = new ConcurrentHashMap<>();
110110

111111

112112
public JpaMetamodelImpl(
@@ -143,13 +143,14 @@ public JpaCompliance getJpaCompliance() {
143143
public <X> ManagedDomainType<X> managedType(String typeName) {
144144
final ManagedDomainType<X> managedType = findManagedType( typeName );
145145
if ( managedType == null ) {
146-
throw new IllegalArgumentException("Not a managed type: " + typeName);
146+
throw new IllegalArgumentException( "Not a managed type: " + typeName );
147147
}
148148
return managedType;
149149
}
150150

151151
@Override
152-
@Nullable public EntityDomainType<?> findEntityType(@Nullable String entityName) {
152+
@Nullable
153+
public EntityDomainType<?> findEntityType(@Nullable String entityName) {
153154
if ( entityName == null ) {
154155
return null;
155156
}
@@ -162,18 +163,19 @@ public EntityDomainType<?> entity(String entityName) {
162163
final EntityDomainType<?> entityType = findEntityType( entityName );
163164
if ( entityType == null ) {
164165
// per JPA
165-
throw new IllegalArgumentException("Not an entity: " + entityName);
166+
throw new IllegalArgumentException( "Not an entity: " + entityName );
166167
}
167168
return entityType;
168169
}
169170

170171
@Override
171-
@Nullable public EmbeddableDomainType<?> findEmbeddableType(@Nullable String embeddableName) {
172+
@Nullable
173+
public EmbeddableDomainType<?> findEmbeddableType(@Nullable String embeddableName) {
172174
if ( embeddableName == null ) {
173175
return null;
174176
}
175177
final ManagedDomainType<?> managedType = managedTypeByName.get( embeddableName );
176-
if ( !( managedType instanceof EmbeddableDomainType<?> embeddableDomainType) ) {
178+
if ( !(managedType instanceof EmbeddableDomainType<?> embeddableDomainType) ) {
177179
return null;
178180
}
179181
return embeddableDomainType;
@@ -183,7 +185,7 @@ public EntityDomainType<?> entity(String entityName) {
183185
public EmbeddableDomainType<?> embeddable(String embeddableName) {
184186
final EmbeddableDomainType<?> embeddableType = findEmbeddableType( embeddableName );
185187
if ( embeddableType == null ) {
186-
throw new IllegalArgumentException("Not an embeddable: " + embeddableName);
188+
throw new IllegalArgumentException( "Not an embeddable: " + embeddableName );
187189
}
188190
return embeddableType;
189191
}
@@ -226,7 +228,8 @@ public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) {
226228
}
227229

228230
@Override
229-
@Nullable public <X> ManagedDomainType<X> findManagedType(Class<X> cls) {
231+
@Nullable
232+
public <X> ManagedDomainType<X> findManagedType(Class<X> cls) {
230233
//noinspection unchecked
231234
return (ManagedDomainType<X>) managedTypeByClass.get( cls );
232235
}
@@ -242,9 +245,10 @@ public <X> ManagedDomainType<X> managedType(Class<X> cls) {
242245
}
243246

244247
@Override
245-
@Nullable public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
248+
@Nullable
249+
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
246250
final ManagedType<?> type = managedTypeByClass.get( cls );
247-
if ( !( type instanceof EntityDomainType<?> ) ) {
251+
if ( !(type instanceof EntityDomainType<?>) ) {
248252
return null;
249253
}
250254
//noinspection unchecked
@@ -263,7 +267,7 @@ public <X> EntityDomainType<X> entity(Class<X> cls) {
263267
@Override
264268
public @Nullable <X> EmbeddableDomainType<X> findEmbeddableType(Class<X> cls) {
265269
final ManagedType<?> type = managedTypeByClass.get( cls );
266-
if ( !( type instanceof EmbeddableDomainType<?> ) ) {
270+
if ( !(type instanceof EmbeddableDomainType<?>) ) {
267271
return null;
268272
}
269273
//noinspection unchecked
@@ -281,7 +285,7 @@ public <X> EmbeddableDomainType<X> embeddable(Class<X> cls) {
281285

282286
private Collection<ManagedDomainType<?>> getAllManagedTypes() {
283287
// should never happen
284-
return switch (jpaMetaModelPopulationSetting) {
288+
return switch ( jpaMetaModelPopulationSetting ) {
285289
case IGNORE_UNSUPPORTED -> managedTypeByClass.values();
286290
case ENABLED -> managedTypeByName.values();
287291
case DISABLED -> emptySet();
@@ -311,7 +315,7 @@ public Set<EmbeddableType<?>> getEmbeddables() {
311315

312316
@Override
313317
public @Nullable Set<String> getEnumTypesForValue(String enumValue) {
314-
return allowedEnumLiteralsToEnumTypeNames.get( enumValue);
318+
return allowedEnumLiteralsToEnumTypeNames.get( enumValue );
315319
}
316320

317321
@Override
@@ -388,7 +392,8 @@ public <T> void addNamedEntityGraph(String graphName, RootGraphImplementor<T> en
388392
}
389393
}
390394

391-
@Override @SuppressWarnings("unchecked")
395+
@Override
396+
@SuppressWarnings("unchecked")
392397
public <T> RootGraphImplementor<T> findEntityGraphByName(String name) {
393398
return (RootGraphImplementor<T>) entityGraphMap.get( name );
394399
}
@@ -490,21 +495,54 @@ private void applyNamedEntityGraphs(Collection<NamedEntityGraphDefinition> named
490495
if ( entityType == null ) {
491496
throw new IllegalArgumentException(
492497
"Attempted to register named entity graph [" + definition.getRegisteredName()
493-
+ "] for unknown entity [" + definition.getEntityName() + "]"
498+
+ "] for unknown entity [" + definition.getEntityName() + "]"
494499

495500
);
496501
}
502+
497503
final NamedEntityGraph namedEntityGraph = definition.getAnnotation();
498504
final RootGraphImpl<?> entityGraph =
499-
createRootGraph( definition.getRegisteredName(), entityType,
500-
namedEntityGraph.includeAllAttributes() );
501-
if ( namedEntityGraph.attributeNodes() != null ) {
502-
applyNamedAttributeNodes( namedEntityGraph.attributeNodes(), namedEntityGraph, entityGraph );
503-
}
505+
createEntityGraph(
506+
namedEntityGraph,
507+
definition.getRegisteredName(),
508+
entityType,
509+
namedEntityGraph.includeAllAttributes()
510+
);
511+
504512
entityGraphMap.put( definition.getRegisteredName(), entityGraph );
505513
}
506514
}
507515

516+
private <T> RootGraphImpl<T> createEntityGraph(
517+
NamedEntityGraph namedEntityGraph,
518+
String registeredName,
519+
EntityDomainType<T> entityType,
520+
boolean includeAllAttributes) {
521+
final RootGraphImpl<T> entityGraph =
522+
createRootGraph( registeredName, entityType, includeAllAttributes );
523+
524+
if ( namedEntityGraph.subclassSubgraphs() != null ) {
525+
Arrays
526+
.stream( namedEntityGraph.subclassSubgraphs() )
527+
.forEach( subclassSubgraph -> {
528+
GraphImplementor<?> subgraph = (GraphImplementor<?>) entityGraph.addTreatedSubgraph(
529+
(Class) subclassSubgraph.type() );
530+
531+
applyNamedAttributeNodes(
532+
subclassSubgraph.attributeNodes(),
533+
namedEntityGraph,
534+
subgraph
535+
);
536+
} );
537+
}
538+
539+
if ( namedEntityGraph.attributeNodes() != null ) {
540+
applyNamedAttributeNodes( namedEntityGraph.attributeNodes(), namedEntityGraph, entityGraph );
541+
}
542+
543+
return entityGraph;
544+
}
545+
508546
private static <T> RootGraphImpl<T> createRootGraph(
509547
String name, EntityDomainType<T> entityType, boolean includeAllAttributes) {
510548
final RootGraphImpl<T> entityGraph = new RootGraphImpl<>( name, entityType );
@@ -521,31 +559,41 @@ private void applyNamedAttributeNodes(
521559
NamedEntityGraph namedEntityGraph,
522560
GraphImplementor<?> graphNode) {
523561
for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) {
524-
final AttributeNodeImplementor<?> attributeNode =
525-
graphNode.findOrCreateAttributeNode( namedAttributeNode.value() );
562+
final String value = namedAttributeNode.value();
563+
final AttributeNodeImplementor<?> attributeNode = (AttributeNodeImplementor<?>) graphNode.addAttributeNode( value );
564+
526565
if ( isNotEmpty( namedAttributeNode.subgraph() ) ) {
527566
applyNamedSubgraphs(
528567
namedEntityGraph,
529568
namedAttributeNode.subgraph(),
530-
attributeNode.makeSubGraph()
569+
attributeNode,
570+
false
531571
);
532572
}
533573
if ( isNotEmpty( namedAttributeNode.keySubgraph() ) ) {
534574
applyNamedSubgraphs(
535575
namedEntityGraph,
536576
namedAttributeNode.keySubgraph(),
537-
attributeNode.makeKeySubGraph()
577+
attributeNode,
578+
true
538579
);
539580
}
540581
}
541582
}
542583

543-
private void applyNamedSubgraphs(
584+
@SuppressWarnings({"unchecked", "rawtypes"})
585+
private <T> void applyNamedSubgraphs(
544586
NamedEntityGraph namedEntityGraph,
545587
String subgraphName,
546-
SubGraphImplementor<?> subgraph) {
588+
AttributeNodeImplementor<T> attributeNode, Boolean isKeySubGraph) {
547589
for ( NamedSubgraph namedSubgraph : namedEntityGraph.subgraphs() ) {
548590
if ( subgraphName.equals( namedSubgraph.name() ) ) {
591+
var isDefaultSubgraphType = namedSubgraph.type().equals( void.class );
592+
Class subGraphType = isDefaultSubgraphType ? null : namedSubgraph.type();
593+
594+
final SubGraphImplementor<?> subgraph = makeAttributeNodeSubgraph( attributeNode, isKeySubGraph,
595+
subGraphType );
596+
549597
applyNamedAttributeNodes(
550598
namedSubgraph.attributeNodes(),
551599
namedEntityGraph,
@@ -555,6 +603,18 @@ private void applyNamedSubgraphs(
555603
}
556604
}
557605

606+
private static <T> SubGraphImplementor<?> makeAttributeNodeSubgraph(AttributeNodeImplementor<T> attributeNode, Boolean isKeySubGraph, Class<T> subGraphType) {
607+
608+
if ( isKeySubGraph ) {
609+
return subGraphType != null ? attributeNode.makeKeySubGraph( subGraphType )
610+
: attributeNode.makeKeySubGraph();
611+
}
612+
613+
return subGraphType != null ?
614+
attributeNode.makeSubGraph( subGraphType ) :
615+
attributeNode.makeSubGraph();
616+
}
617+
558618
private <X> Class<X> resolveRequestedClass(String entityName) {
559619
try {
560620
return getServiceRegistry().requireService( ClassLoaderService.class )
@@ -609,8 +669,8 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
609669
// incorrect results
610670
final ManagedDomainType<?> superType = managedType.getSuperType();
611671
if ( superType != null
612-
&& superType.getPersistenceType() == Type.PersistenceType.ENTITY
613-
&& javaType.isAssignableFrom( superType.getJavaType() ) ) {
672+
&& superType.getPersistenceType() == Type.PersistenceType.ENTITY
673+
&& javaType.isAssignableFrom( superType.getJavaType() ) ) {
614674
continue;
615675
}
616676

@@ -631,7 +691,8 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
631691
}
632692
}
633693

634-
throw new EntityTypeException( "Could not resolve entity class '" + javaType.getName() + "'", javaType.getName() );
694+
throw new EntityTypeException( "Could not resolve entity class '" + javaType.getName() + "'",
695+
javaType.getName() );
635696
}
636697

637698
@Override
@@ -719,7 +780,7 @@ private void populateStaticMetamodel(MetadataImplementor bootMetamodel, Metadata
719780
-> injectTypedQueryReference( definition, namedQueryMetamodelClass( definition, context ) ) );
720781
bootMetamodel.visitNamedNativeQueryDefinitions( definition
721782
-> injectTypedQueryReference( definition, namedQueryMetamodelClass( definition, context ) ) );
722-
bootMetamodel.getNamedEntityGraphs().values().forEach(definition
783+
bootMetamodel.getNamedEntityGraphs().values().forEach( definition
723784
-> injectEntityGraph( definition, graphMetamodelClass( definition, context ), this ) );
724785
}
725786

0 commit comments

Comments
 (0)