Skip to content

Commit 4321cca

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

File tree

3 files changed

+575
-35
lines changed

3 files changed

+575
-35
lines changed

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

Lines changed: 118 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.stream.Collectors;
2121

2222
import org.checkerframework.checker.nullness.qual.Nullable;
23+
2324
import org.hibernate.boot.model.NamedEntityGraphDefinition;
2425
import org.hibernate.boot.query.NamedQueryDefinition;
2526
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
@@ -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,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

Comments
 (0)