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 }
@@ -403,8 +408,7 @@ public <T> List<RootGraphImplementor<? super T>> findEntityGraphsByJavaType(Clas
403408 final List <RootGraphImplementor <? super T >> results = new ArrayList <>();
404409 for ( RootGraphImplementor <?> entityGraph : entityGraphMap .values () ) {
405410 if ( entityGraph .appliesTo ( entityType ) ) {
406- @ SuppressWarnings ("unchecked" )
407- final RootGraphImplementor <? super T > result = (RootGraphImplementor <? super T >) entityGraph ;
411+ @ SuppressWarnings ("unchecked" ) final RootGraphImplementor <? super T > result = (RootGraphImplementor <? super T >) entityGraph ;
408412 results .add ( result );
409413 }
410414 }
@@ -494,17 +498,48 @@ private void applyNamedEntityGraphs(Collection<NamedEntityGraphDefinition> named
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,44 @@ 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 (
561+ value );
562+
526563 if ( isNotEmpty ( namedAttributeNode .subgraph () ) ) {
527564 applyNamedSubgraphs (
528565 namedEntityGraph ,
529566 namedAttributeNode .subgraph (),
530- attributeNode .makeSubGraph ()
567+ attributeNode ,
568+ false
531569 );
532570 }
533571 if ( isNotEmpty ( namedAttributeNode .keySubgraph () ) ) {
534572 applyNamedSubgraphs (
535573 namedEntityGraph ,
536574 namedAttributeNode .keySubgraph (),
537- attributeNode .makeKeySubGraph ()
575+ attributeNode ,
576+ true
538577 );
539578 }
540579 }
541580 }
542581
543- private void applyNamedSubgraphs (
582+ @ SuppressWarnings ({ "unchecked" , "rawtypes" })
583+ private <T > void applyNamedSubgraphs (
544584 NamedEntityGraph namedEntityGraph ,
545585 String subgraphName ,
546- SubGraphImplementor <?> subgraph ) {
586+ AttributeNodeImplementor < T > attributeNode , Boolean isKeySubGraph ) {
547587 for ( NamedSubgraph namedSubgraph : namedEntityGraph .subgraphs () ) {
548588 if ( subgraphName .equals ( namedSubgraph .name () ) ) {
589+ var isDefaultSubgraphType = namedSubgraph .type ().equals ( void .class );
590+ Class subGraphType = isDefaultSubgraphType ? null : namedSubgraph .type ();
591+
592+ final SubGraphImplementor <?> subgraph = makeAttributeNodeSubgraph (
593+ attributeNode , isKeySubGraph ,
594+ subGraphType
595+ );
596+
549597 applyNamedAttributeNodes (
550598 namedSubgraph .attributeNodes (),
551599 namedEntityGraph ,
@@ -555,6 +603,21 @@ private void applyNamedSubgraphs(
555603 }
556604 }
557605
606+ private static <T > SubGraphImplementor <?> makeAttributeNodeSubgraph (
607+ AttributeNodeImplementor <T > attributeNode ,
608+ Boolean isKeySubGraph ,
609+ Class <T > subGraphType ) {
610+
611+ if ( isKeySubGraph ) {
612+ return subGraphType != null ? attributeNode .makeKeySubGraph ( subGraphType )
613+ : attributeNode .makeKeySubGraph ();
614+ }
615+
616+ return subGraphType != null ?
617+ attributeNode .makeSubGraph ( subGraphType ) :
618+ attributeNode .makeSubGraph ();
619+ }
620+
558621 private <X > Class <X > resolveRequestedClass (String entityName ) {
559622 try {
560623 return getServiceRegistry ().requireService ( ClassLoaderService .class )
@@ -631,7 +694,10 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
631694 }
632695 }
633696
634- throw new EntityTypeException ( "Could not resolve entity class '" + javaType .getName () + "'" , javaType .getName () );
697+ throw new EntityTypeException (
698+ "Could not resolve entity class '" + javaType .getName () + "'" ,
699+ javaType .getName ()
700+ );
635701 }
636702
637703 @ Override
@@ -716,11 +782,30 @@ public void processJpa(
716782
717783 private void populateStaticMetamodel (MetadataImplementor bootMetamodel , MetadataContext context ) {
718784 bootMetamodel .visitNamedHqlQueryDefinitions ( definition
719- -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
785+ -> injectTypedQueryReference (
786+ definition ,
787+ namedQueryMetamodelClass (
788+ definition ,
789+ context
790+ )
791+ ) );
720792 bootMetamodel .visitNamedNativeQueryDefinitions ( definition
721- -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
722- bootMetamodel .getNamedEntityGraphs ().values ().forEach (definition
723- -> injectEntityGraph ( definition , graphMetamodelClass ( definition , context ), this ) );
793+ -> injectTypedQueryReference (
794+ definition ,
795+ namedQueryMetamodelClass (
796+ definition ,
797+ context
798+ )
799+ ) );
800+ bootMetamodel .getNamedEntityGraphs ().values ().forEach ( definition
801+ -> injectEntityGraph (
802+ definition ,
803+ graphMetamodelClass (
804+ definition ,
805+ context
806+ ),
807+ this
808+ ) );
724809 }
725810
726811 private Class <?> namedQueryMetamodelClass (NamedQueryDefinition <?> definition , MetadataContext context ) {
@@ -763,8 +848,7 @@ private <T> EntityDomainType<T> locateOrBuildEntityType(
763848 PersistentClass persistentClass ,
764849 MetadataContext context ,
765850 final TypeConfiguration typeConfiguration ) {
766- @ SuppressWarnings ("unchecked" )
767- final EntityDomainType <T > entityType =
851+ @ SuppressWarnings ("unchecked" ) final EntityDomainType <T > entityType =
768852 (EntityDomainType <T >)
769853 context .locateEntityType ( persistentClass );
770854 return entityType == null
@@ -816,8 +900,7 @@ private <T> MappedSuperclassDomainType<T> locateOrBuildMappedSuperclassType(
816900 MappedSuperclass mappedSuperclass ,
817901 MetadataContext context ,
818902 TypeConfiguration typeConfiguration ) {
819- @ SuppressWarnings ("unchecked" )
820- final MappedSuperclassDomainType <T > mappedSuperclassType =
903+ @ SuppressWarnings ("unchecked" ) final MappedSuperclassDomainType <T > mappedSuperclassType =
821904 (MappedSuperclassDomainType <T >)
822905 context .locateMappedSuperclassType ( mappedSuperclass );
823906 return mappedSuperclassType == null
0 commit comments