7373import static org .hibernate .metamodel .internal .InjectionHelper .injectTypedQueryReference ;
7474
7575/**
76- *
7776 * @author Steve Ebersole
7877 */
7978public class JpaMetamodelImpl implements JpaMetamodelImplementor , Serializable {
@@ -106,7 +105,7 @@ private ImportInfo(String importedName, Class<T> loadedClass) {
106105 private final Map <Class <?>, String > entityProxyInterfaceMap = new HashMap <>();
107106
108107 private final Map <String , ImportInfo <?>> nameToImportMap = new ConcurrentHashMap <>();
109- private final Map <String ,Object > knownInvalidnameToImportMap = new ConcurrentHashMap <>();
108+ private final Map <String , Object > knownInvalidnameToImportMap = new ConcurrentHashMap <>();
110109
111110
112111 public JpaMetamodelImpl (
@@ -143,13 +142,14 @@ public JpaCompliance getJpaCompliance() {
143142 public <X > ManagedDomainType <X > managedType (String typeName ) {
144143 final ManagedDomainType <X > managedType = findManagedType ( typeName );
145144 if ( managedType == null ) {
146- throw new IllegalArgumentException ("Not a managed type: " + typeName );
145+ throw new IllegalArgumentException ( "Not a managed type: " + typeName );
147146 }
148147 return managedType ;
149148 }
150149
151150 @ Override
152- @ Nullable public EntityDomainType <?> findEntityType (@ Nullable String entityName ) {
151+ @ Nullable
152+ public EntityDomainType <?> findEntityType (@ Nullable String entityName ) {
153153 if ( entityName == null ) {
154154 return null ;
155155 }
@@ -162,18 +162,19 @@ public EntityDomainType<?> entity(String entityName) {
162162 final EntityDomainType <?> entityType = findEntityType ( entityName );
163163 if ( entityType == null ) {
164164 // per JPA
165- throw new IllegalArgumentException ("Not an entity: " + entityName );
165+ throw new IllegalArgumentException ( "Not an entity: " + entityName );
166166 }
167167 return entityType ;
168168 }
169169
170170 @ Override
171- @ Nullable public EmbeddableDomainType <?> findEmbeddableType (@ Nullable String embeddableName ) {
171+ @ Nullable
172+ public EmbeddableDomainType <?> findEmbeddableType (@ Nullable String embeddableName ) {
172173 if ( embeddableName == null ) {
173174 return null ;
174175 }
175176 final ManagedDomainType <?> managedType = managedTypeByName .get ( embeddableName );
176- if ( !( managedType instanceof EmbeddableDomainType <?> embeddableDomainType ) ) {
177+ if ( !(managedType instanceof EmbeddableDomainType <?> embeddableDomainType ) ) {
177178 return null ;
178179 }
179180 return embeddableDomainType ;
@@ -183,7 +184,7 @@ public EntityDomainType<?> entity(String entityName) {
183184 public EmbeddableDomainType <?> embeddable (String embeddableName ) {
184185 final EmbeddableDomainType <?> embeddableType = findEmbeddableType ( embeddableName );
185186 if ( embeddableType == null ) {
186- throw new IllegalArgumentException ("Not an embeddable: " + embeddableName );
187+ throw new IllegalArgumentException ( "Not an embeddable: " + embeddableName );
187188 }
188189 return embeddableType ;
189190 }
@@ -226,7 +227,8 @@ public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) {
226227 }
227228
228229 @ Override
229- @ Nullable public <X > ManagedDomainType <X > findManagedType (Class <X > cls ) {
230+ @ Nullable
231+ public <X > ManagedDomainType <X > findManagedType (Class <X > cls ) {
230232 //noinspection unchecked
231233 return (ManagedDomainType <X >) managedTypeByClass .get ( cls );
232234 }
@@ -242,9 +244,10 @@ public <X> ManagedDomainType<X> managedType(Class<X> cls) {
242244 }
243245
244246 @ Override
245- @ Nullable public <X > EntityDomainType <X > findEntityType (Class <X > cls ) {
247+ @ Nullable
248+ public <X > EntityDomainType <X > findEntityType (Class <X > cls ) {
246249 final ManagedType <?> type = managedTypeByClass .get ( cls );
247- if ( !( type instanceof EntityDomainType <?> ) ) {
250+ if ( !(type instanceof EntityDomainType <?>) ) {
248251 return null ;
249252 }
250253 //noinspection unchecked
@@ -263,7 +266,7 @@ public <X> EntityDomainType<X> entity(Class<X> cls) {
263266 @ Override
264267 public @ Nullable <X > EmbeddableDomainType <X > findEmbeddableType (Class <X > cls ) {
265268 final ManagedType <?> type = managedTypeByClass .get ( cls );
266- if ( !( type instanceof EmbeddableDomainType <?> ) ) {
269+ if ( !(type instanceof EmbeddableDomainType <?>) ) {
267270 return null ;
268271 }
269272 //noinspection unchecked
@@ -281,7 +284,7 @@ public <X> EmbeddableDomainType<X> embeddable(Class<X> cls) {
281284
282285 private Collection <ManagedDomainType <?>> getAllManagedTypes () {
283286 // should never happen
284- return switch (jpaMetaModelPopulationSetting ) {
287+ return switch ( jpaMetaModelPopulationSetting ) {
285288 case IGNORE_UNSUPPORTED -> managedTypeByClass .values ();
286289 case ENABLED -> managedTypeByName .values ();
287290 case DISABLED -> emptySet ();
@@ -311,7 +314,7 @@ public Set<EmbeddableType<?>> getEmbeddables() {
311314
312315 @ Override
313316 public @ Nullable Set <String > getEnumTypesForValue (String enumValue ) {
314- return allowedEnumLiteralsToEnumTypeNames .get ( enumValue );
317+ return allowedEnumLiteralsToEnumTypeNames .get ( enumValue );
315318 }
316319
317320 @ Override
@@ -388,7 +391,8 @@ public <T> void addNamedEntityGraph(String graphName, RootGraphImplementor<T> en
388391 }
389392 }
390393
391- @ Override @ SuppressWarnings ("unchecked" )
394+ @ Override
395+ @ SuppressWarnings ("unchecked" )
392396 public <T > RootGraphImplementor <T > findEntityGraphByName (String name ) {
393397 return (RootGraphImplementor <T >) entityGraphMap .get ( name );
394398 }
@@ -490,21 +494,52 @@ private void applyNamedEntityGraphs(Collection<NamedEntityGraphDefinition> named
490494 if ( entityType == null ) {
491495 throw new IllegalArgumentException (
492496 "Attempted to register named entity graph [" + definition .getRegisteredName ()
493- + "] for unknown entity [" + definition .getEntityName () + "]"
497+ + "] for unknown entity [" + definition .getEntityName () + "]"
494498
495499 );
496500 }
501+
497502 final NamedEntityGraph namedEntityGraph = definition .getAnnotation ();
498503 final RootGraphImpl <?> entityGraph =
499- createRootGraph ( definition .getRegisteredName (), entityType ,
500- namedEntityGraph .includeAllAttributes () );
501- if ( namedEntityGraph .attributeNodes () != null ) {
502- applyNamedAttributeNodes ( namedEntityGraph .attributeNodes (), namedEntityGraph , entityGraph );
503- }
504+ createEntityGraph (
505+ namedEntityGraph ,
506+ definition .getRegisteredName (),
507+ entityType ,
508+ namedEntityGraph .includeAllAttributes ()
509+ );
510+
504511 entityGraphMap .put ( definition .getRegisteredName (), entityGraph );
505512 }
506513 }
507514
515+ private <T > RootGraphImpl <T > createEntityGraph (
516+ NamedEntityGraph namedEntityGraph ,
517+ String registeredName ,
518+ EntityDomainType <T > entityType ,
519+ boolean includeAllAttributes ) {
520+ final RootGraphImpl <T > entityGraph =
521+ createRootGraph ( registeredName , entityType , includeAllAttributes );
522+
523+ if ( namedEntityGraph .subclassSubgraphs () != null ) {
524+ for (var subclassSubgraph : namedEntityGraph .subclassSubgraphs ()) {
525+ GraphImplementor <?> subgraph = (GraphImplementor <?>) entityGraph .addTreatedSubgraph (
526+ (Class ) subclassSubgraph .type () );
527+
528+ applyNamedAttributeNodes (
529+ subclassSubgraph .attributeNodes (),
530+ namedEntityGraph ,
531+ subgraph
532+ );
533+ }
534+ }
535+
536+ if ( namedEntityGraph .attributeNodes () != null ) {
537+ applyNamedAttributeNodes ( namedEntityGraph .attributeNodes (), namedEntityGraph , entityGraph );
538+ }
539+
540+ return entityGraph ;
541+ }
542+
508543 private static <T > RootGraphImpl <T > createRootGraph (
509544 String name , EntityDomainType <T > entityType , boolean includeAllAttributes ) {
510545 final RootGraphImpl <T > entityGraph = new RootGraphImpl <>( name , entityType );
@@ -521,31 +556,41 @@ private void applyNamedAttributeNodes(
521556 NamedEntityGraph namedEntityGraph ,
522557 GraphImplementor <?> graphNode ) {
523558 for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) {
524- final AttributeNodeImplementor <?> attributeNode =
525- graphNode .findOrCreateAttributeNode ( namedAttributeNode .value () );
559+ final String value = namedAttributeNode .value ();
560+ final AttributeNodeImplementor <?> attributeNode = (AttributeNodeImplementor <?>) graphNode .addAttributeNode ( value );
561+
526562 if ( isNotEmpty ( namedAttributeNode .subgraph () ) ) {
527563 applyNamedSubgraphs (
528564 namedEntityGraph ,
529565 namedAttributeNode .subgraph (),
530- attributeNode .makeSubGraph ()
566+ attributeNode ,
567+ false
531568 );
532569 }
533570 if ( isNotEmpty ( namedAttributeNode .keySubgraph () ) ) {
534571 applyNamedSubgraphs (
535572 namedEntityGraph ,
536573 namedAttributeNode .keySubgraph (),
537- attributeNode .makeKeySubGraph ()
574+ attributeNode ,
575+ true
538576 );
539577 }
540578 }
541579 }
542580
543- private void applyNamedSubgraphs (
581+ @ SuppressWarnings ({"unchecked" , "rawtypes" })
582+ private <T > void applyNamedSubgraphs (
544583 NamedEntityGraph namedEntityGraph ,
545584 String subgraphName ,
546- SubGraphImplementor <?> subgraph ) {
585+ AttributeNodeImplementor < T > attributeNode , Boolean isKeySubGraph ) {
547586 for ( NamedSubgraph namedSubgraph : namedEntityGraph .subgraphs () ) {
548587 if ( subgraphName .equals ( namedSubgraph .name () ) ) {
588+ var isDefaultSubgraphType = namedSubgraph .type ().equals ( void .class );
589+ Class subGraphType = isDefaultSubgraphType ? null : namedSubgraph .type ();
590+
591+ final SubGraphImplementor <?> subgraph = makeAttributeNodeSubgraph ( attributeNode , isKeySubGraph ,
592+ subGraphType );
593+
549594 applyNamedAttributeNodes (
550595 namedSubgraph .attributeNodes (),
551596 namedEntityGraph ,
@@ -555,6 +600,18 @@ private void applyNamedSubgraphs(
555600 }
556601 }
557602
603+ private static <T > SubGraphImplementor <?> makeAttributeNodeSubgraph (AttributeNodeImplementor <T > attributeNode , Boolean isKeySubGraph , Class <T > subGraphType ) {
604+
605+ if ( isKeySubGraph ) {
606+ return subGraphType != null ? attributeNode .makeKeySubGraph ( subGraphType )
607+ : attributeNode .makeKeySubGraph ();
608+ }
609+
610+ return subGraphType != null ?
611+ attributeNode .makeSubGraph ( subGraphType ) :
612+ attributeNode .makeSubGraph ();
613+ }
614+
558615 private <X > Class <X > resolveRequestedClass (String entityName ) {
559616 try {
560617 return getServiceRegistry ().requireService ( ClassLoaderService .class )
@@ -609,8 +666,8 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
609666 // incorrect results
610667 final ManagedDomainType <?> superType = managedType .getSuperType ();
611668 if ( superType != null
612- && superType .getPersistenceType () == Type .PersistenceType .ENTITY
613- && javaType .isAssignableFrom ( superType .getJavaType () ) ) {
669+ && superType .getPersistenceType () == Type .PersistenceType .ENTITY
670+ && javaType .isAssignableFrom ( superType .getJavaType () ) ) {
614671 continue ;
615672 }
616673
@@ -631,7 +688,8 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
631688 }
632689 }
633690
634- throw new EntityTypeException ( "Could not resolve entity class '" + javaType .getName () + "'" , javaType .getName () );
691+ throw new EntityTypeException ( "Could not resolve entity class '" + javaType .getName () + "'" ,
692+ javaType .getName () );
635693 }
636694
637695 @ Override
@@ -719,7 +777,7 @@ private void populateStaticMetamodel(MetadataImplementor bootMetamodel, Metadata
719777 -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
720778 bootMetamodel .visitNamedNativeQueryDefinitions ( definition
721779 -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
722- bootMetamodel .getNamedEntityGraphs ().values ().forEach (definition
780+ bootMetamodel .getNamedEntityGraphs ().values ().forEach ( definition
723781 -> injectEntityGraph ( definition , graphMetamodelClass ( definition , context ), this ) );
724782 }
725783
0 commit comments