2020import java .util .stream .Collectors ;
2121
2222import org .checkerframework .checker .nullness .qual .Nullable ;
23+
2324import org .hibernate .boot .model .NamedEntityGraphDefinition ;
2425import org .hibernate .boot .query .NamedQueryDefinition ;
2526import org .hibernate .boot .registry .classloading .spi .ClassLoaderService ;
7374import static org .hibernate .metamodel .internal .InjectionHelper .injectTypedQueryReference ;
7475
7576/**
76- *
7777 * @author Steve Ebersole
7878 */
7979public 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,7 +245,8 @@ 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 );
247251 if ( !( type instanceof EntityDomainType <?> ) ) {
248252 return null ;
@@ -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 }
@@ -494,17 +499,48 @@ private void applyNamedEntityGraphs(Collection<NamedEntityGraphDefinition> named
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+ for ( var subclassSubgraph : namedEntityGraph .subclassSubgraphs () ) {
526+ GraphImplementor <?> subgraph = (GraphImplementor <?>) entityGraph .addTreatedSubgraph (
527+ (Class ) subclassSubgraph .type () );
528+
529+ applyNamedAttributeNodes (
530+ subclassSubgraph .attributeNodes (),
531+ namedEntityGraph ,
532+ subgraph
533+ );
534+ }
535+ }
536+
537+ if ( namedEntityGraph .attributeNodes () != null ) {
538+ applyNamedAttributeNodes ( namedEntityGraph .attributeNodes (), namedEntityGraph , entityGraph );
539+ }
540+
541+ return entityGraph ;
542+ }
543+
508544 private static <T > RootGraphImpl <T > createRootGraph (
509545 String name , EntityDomainType <T > entityType , boolean includeAllAttributes ) {
510546 final RootGraphImpl <T > entityGraph = new RootGraphImpl <>( name , entityType );
@@ -521,31 +557,44 @@ private void applyNamedAttributeNodes(
521557 NamedEntityGraph namedEntityGraph ,
522558 GraphImplementor <?> graphNode ) {
523559 for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) {
524- final AttributeNodeImplementor <?> attributeNode =
525- graphNode .findOrCreateAttributeNode ( namedAttributeNode .value () );
560+ final String value = namedAttributeNode .value ();
561+ final AttributeNodeImplementor <?> attributeNode = (AttributeNodeImplementor <?>) graphNode .addAttributeNode (
562+ value );
563+
526564 if ( isNotEmpty ( namedAttributeNode .subgraph () ) ) {
527565 applyNamedSubgraphs (
528566 namedEntityGraph ,
529567 namedAttributeNode .subgraph (),
530- attributeNode .makeSubGraph ()
568+ attributeNode ,
569+ false
531570 );
532571 }
533572 if ( isNotEmpty ( namedAttributeNode .keySubgraph () ) ) {
534573 applyNamedSubgraphs (
535574 namedEntityGraph ,
536575 namedAttributeNode .keySubgraph (),
537- attributeNode .makeKeySubGraph ()
576+ attributeNode ,
577+ true
538578 );
539579 }
540580 }
541581 }
542582
543- private void applyNamedSubgraphs (
583+ @ SuppressWarnings ({ "unchecked" , "rawtypes" })
584+ private <T > void applyNamedSubgraphs (
544585 NamedEntityGraph namedEntityGraph ,
545586 String subgraphName ,
546- SubGraphImplementor <?> subgraph ) {
587+ AttributeNodeImplementor < T > attributeNode , Boolean isKeySubGraph ) {
547588 for ( NamedSubgraph namedSubgraph : namedEntityGraph .subgraphs () ) {
548589 if ( subgraphName .equals ( namedSubgraph .name () ) ) {
590+ final var isDefaultSubgraphType = namedSubgraph .type ().equals ( void .class );
591+ final Class subGraphType = isDefaultSubgraphType ? null : namedSubgraph .type ();
592+
593+ final SubGraphImplementor <?> subgraph = makeAttributeNodeSubgraph (
594+ attributeNode , isKeySubGraph ,
595+ subGraphType
596+ );
597+
549598 applyNamedAttributeNodes (
550599 namedSubgraph .attributeNodes (),
551600 namedEntityGraph ,
@@ -555,6 +604,21 @@ private void applyNamedSubgraphs(
555604 }
556605 }
557606
607+ private static <T > SubGraphImplementor <?> makeAttributeNodeSubgraph (
608+ AttributeNodeImplementor <T > attributeNode ,
609+ Boolean isKeySubGraph ,
610+ Class <T > subGraphType ) {
611+
612+ if ( isKeySubGraph ) {
613+ return subGraphType != null ? attributeNode .makeKeySubGraph ( subGraphType )
614+ : attributeNode .makeKeySubGraph ();
615+ }
616+
617+ return subGraphType != null ?
618+ attributeNode .makeSubGraph ( subGraphType ) :
619+ attributeNode .makeSubGraph ();
620+ }
621+
558622 private <X > Class <X > resolveRequestedClass (String entityName ) {
559623 try {
560624 return getServiceRegistry ().requireService ( ClassLoaderService .class )
@@ -631,7 +695,10 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
631695 }
632696 }
633697
634- throw new EntityTypeException ( "Could not resolve entity class '" + javaType .getName () + "'" , javaType .getName () );
698+ throw new EntityTypeException (
699+ "Could not resolve entity class '" + javaType .getName () + "'" ,
700+ javaType .getName ()
701+ );
635702 }
636703
637704 @ Override
@@ -716,11 +783,30 @@ public void processJpa(
716783
717784 private void populateStaticMetamodel (MetadataImplementor bootMetamodel , MetadataContext context ) {
718785 bootMetamodel .visitNamedHqlQueryDefinitions ( definition
719- -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
786+ -> injectTypedQueryReference (
787+ definition ,
788+ namedQueryMetamodelClass (
789+ definition ,
790+ context
791+ )
792+ ) );
720793 bootMetamodel .visitNamedNativeQueryDefinitions ( definition
721- -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
722- bootMetamodel .getNamedEntityGraphs ().values ().forEach (definition
723- -> injectEntityGraph ( definition , graphMetamodelClass ( definition , context ), this ) );
794+ -> injectTypedQueryReference (
795+ definition ,
796+ namedQueryMetamodelClass (
797+ definition ,
798+ context
799+ )
800+ ) );
801+ bootMetamodel .getNamedEntityGraphs ().values ().forEach ( definition
802+ -> injectEntityGraph (
803+ definition ,
804+ graphMetamodelClass (
805+ definition ,
806+ context
807+ ),
808+ this
809+ ) );
724810 }
725811
726812 private Class <?> namedQueryMetamodelClass (NamedQueryDefinition <?> definition , MetadataContext context ) {
@@ -764,9 +850,7 @@ private <T> EntityDomainType<T> locateOrBuildEntityType(
764850 MetadataContext context ,
765851 final TypeConfiguration typeConfiguration ) {
766852 @ SuppressWarnings ("unchecked" )
767- final EntityDomainType <T > entityType =
768- (EntityDomainType <T >)
769- context .locateEntityType ( persistentClass );
853+ final EntityDomainType <T > entityType = (EntityDomainType <T >) context .locateEntityType ( persistentClass );
770854 return entityType == null
771855 ? buildEntityType ( persistentClass , context , typeConfiguration )
772856 : entityType ;
@@ -818,8 +902,7 @@ private <T> MappedSuperclassDomainType<T> locateOrBuildMappedSuperclassType(
818902 TypeConfiguration typeConfiguration ) {
819903 @ SuppressWarnings ("unchecked" )
820904 final MappedSuperclassDomainType <T > mappedSuperclassType =
821- (MappedSuperclassDomainType <T >)
822- context .locateMappedSuperclassType ( mappedSuperclass );
905+ (MappedSuperclassDomainType <T >) context .locateMappedSuperclassType ( mappedSuperclass );
823906 return mappedSuperclassType == null
824907 ? buildMappedSuperclassType ( mappedSuperclass , context , typeConfiguration )
825908 : mappedSuperclassType ;
0 commit comments