2323import org .hibernate .metamodel .model .domain .ManagedDomainType ;
2424import org .hibernate .metamodel .model .domain .MapPersistentAttribute ;
2525import org .hibernate .metamodel .model .domain .PersistentAttribute ;
26+ import org .hibernate .metamodel .model .domain .PluralPersistentAttribute ;
2627import org .hibernate .query .sqm .SqmPathSource ;
2728
2829import jakarta .persistence .metamodel .Attribute ;
3940public abstract class AbstractGraph <J > extends AbstractGraphNode <J > implements GraphImplementor <J > {
4041
4142 private final ManagedDomainType <J > managedType ;
43+ private final Map <Class <?>, SubGraphImplementor <?>> subgraphs = new HashMap <>(1 );
4244 private Map <PersistentAttribute <? super J ,?>, AttributeNodeImplementor <?>> attributeNodes ;
43- private List <SubGraphImplementor <? extends J >> subgraphs ;
4445
4546 public AbstractGraph (ManagedDomainType <J > managedType , boolean mutable ) {
4647 super ( mutable );
4748 this .managedType = managedType ;
49+ if ( this instanceof SubGraphImplementor <?> self ) {
50+ subgraphs .put ( managedType .getJavaType (), self );
51+ }
4852 }
4953
5054 protected AbstractGraph (ManagedDomainType <J > managedType , GraphImplementor <? super J > graph , boolean mutable ) {
5155 this ( managedType , mutable );
5256 attributeNodes = new HashMap <>( graph .getAttributeNodesByAttribute ().size () );
53- graph .getAttributeNodesByAttribute ()
54- .forEach ( (attribute , node ) -> attributeNodes .put ( attribute , node .makeCopy ( mutable ) ) );
57+ mergeInternal ( graph , mutable );
5558 }
5659
5760 protected AbstractGraph (GraphImplementor <J > graph , boolean mutable ) {
@@ -76,42 +79,63 @@ public RootGraphImplementor<J> makeRootGraph(String name, boolean mutable) {
7679 }
7780
7881 @ Override
79- public void merge (GraphImplementor <J > graph ) {
82+ public void merge (GraphImplementor <? super J > graph ) {
83+ merge ( graph , true );
84+ }
85+
86+ @ Override
87+ public void merge (GraphImplementor <? super J > graph , boolean mutable ) {
8088 if ( graph != null ) {
8189 verifyMutability ();
82- graph .getAttributeNodesByAttribute ().forEach ( (attribute , node ) -> {
83- final AttributeNodeImplementor <?> existingNode = findAttributeNode ( attribute );
84- if ( existingNode != null ) {
85- // keep the local one, but merge in the incoming one
86- mergeNode ( node , existingNode );
90+ mergeInternal ( graph , mutable );
91+ }
92+ }
93+
94+ private void mergeInternal (GraphImplementor <? super J > graph , boolean mutable ) {
95+ graph .getAttributeNodesByAttribute ().forEach ( (attribute , node ) -> {
96+ final AttributeNodeImplementor <?> existingNode = findAttributeNode ( attribute );
97+ if ( existingNode != null ) {
98+ // keep the local one, but merge in the incoming one
99+ mergeNode ( node , existingNode , mutable );
100+ }
101+ else {
102+ addAttributeNode ( attribute , node .makeCopy ( mutable ), mutable );
103+ }
104+ } );
105+ graph .getSubGraphMap ().forEach ( (type , subgraph ) -> {
106+ if ( subgraph != graph ) {
107+ final SubGraphImplementor <?> existing = subgraphs .get ( type );
108+ if ( existing != null ) {
109+ existing .merge ( (SubGraphImplementor ) subgraph , mutable );
87110 }
88111 else {
89- addAttributeNode ( attribute , node .makeCopy ( true ) );
112+ subgraphs . put ( type , subgraph .makeCopy ( mutable ) );
90113 }
91- } );
92- }
114+ }
115+ } );
93116 }
94117
95- private static <T > void mergeNode (AttributeNodeImplementor <?> node , AttributeNodeImplementor <T > existingNode ) {
118+ private static <T > void mergeNode (
119+ AttributeNodeImplementor <?> node , AttributeNodeImplementor <T > existingNode , boolean mutable ) {
96120 if ( existingNode .getAttributeDescriptor () == node .getAttributeDescriptor () ) {
97121 @ SuppressWarnings ("unchecked" ) // safe, we just checked
98122 final AttributeNodeImplementor <T > castNode = (AttributeNodeImplementor <T >) node ;
99- existingNode .merge ( castNode );
123+ existingNode .merge ( castNode , mutable );
100124 }
101125 else {
102126 throw new AssertionFailure ( "Attributes should have been identical" );
103127 }
104128 }
105129
106- private <T > void addAttributeNode (PersistentAttribute <? super J , ?> attribute , AttributeNodeImplementor <T > node ) {
130+ private <T > void addAttributeNode (
131+ PersistentAttribute <? super J , ?> attribute , AttributeNodeImplementor <T > node , boolean mutable ) {
107132 final AttributeNodeImplementor <T > attributeNode = getNodeForPut ( node .getAttributeDescriptor () );
108133 if ( attributeNode == null ) {
109134 attributeNodes .put ( attribute , node );
110135 }
111136 else {
112137 // we assume the subgraph has been properly copied if needed
113- node .getSubGraphMap ().forEach ( (subtype , subgraph ) -> attributeNode .addSubGraph ( subgraph ) );
114- node .getKeySubGraphMap ().forEach ( (subtype , subgraph ) -> attributeNode .addKeySubGraph ( subgraph ) );
138+ node .merge ( attributeNode , mutable );
115139 }
116140 }
117141
@@ -126,11 +150,13 @@ public <AJ> AttributeNodeImplementor<AJ> findAttributeNode(String attributeName)
126150 @ SuppressWarnings ("unchecked" ) // The JPA API is unsafe by nature
127151 final PersistentAttribute <? super J , AJ > persistentAttribute = (PersistentAttribute <? super J , AJ >) attribute ;
128152 final AttributeNodeImplementor <AJ > node = attribute == null ? null : findAttributeNode ( persistentAttribute );
129- if ( node == null && subgraphs != null ) {
130- for ( SubGraphImplementor <? extends J > subgraph : subgraphs ) {
131- final AttributeNodeImplementor <AJ > subgraphNode = subgraph .findAttributeNode ( attributeName );
132- if ( subgraphNode != null ) {
133- return subgraphNode ;
153+ if ( node == null ) {
154+ for ( SubGraphImplementor <?> subgraph : subgraphs .values () ) {
155+ if ( subgraph != this ) {
156+ final AttributeNodeImplementor <AJ > subgraphNode = subgraph .findAttributeNode ( attributeName );
157+ if ( subgraphNode != null ) {
158+ return subgraphNode ;
159+ }
134160 }
135161 }
136162 return null ;
@@ -272,12 +298,22 @@ public <AJ> SubGraphImplementor<AJ> addSubGraph(PersistentAttribute<? super J, ?
272298 }
273299
274300 @ Override
275- public <AJ > SubGraphImplementor <AJ > addSubGraph (MapPersistentAttribute <? super J , ? super AJ , ? > attribute , ManagedDomainType <AJ > subtype ) {
301+ public <AJ > SubGraphImplementor <AJ > addSubGraph (PersistentAttribute <? super J , ? super AJ > attribute , ManagedDomainType <AJ > subtype ) {
276302 return findOrCreateAttributeNode ( attribute ).makeSubGraph ( subtype );
277303 }
278304
279305 @ Override
280- public <AJ > SubGraphImplementor <AJ > addKeySubGraph (PersistentAttribute <? super J , ? super AJ > attribute , ManagedDomainType <AJ > subtype ) {
306+ public <AJ > SubGraphImplementor <AJ > addElementSubGraph (PluralPersistentAttribute <? super J , ?, ? super AJ > attribute , Class <AJ > type ) {
307+ return findOrCreateAttributeNode ( attribute ).makeSubGraph ( type );
308+ }
309+
310+ @ Override
311+ public <AJ > SubGraphImplementor <AJ > addElementSubGraph (PluralPersistentAttribute <? super J , ?, ? super AJ > attribute , ManagedDomainType <AJ > type ) {
312+ return findOrCreateAttributeNode ( attribute ).makeSubGraph ( type );
313+ }
314+
315+ @ Override
316+ public <AJ > SubGraphImplementor <AJ > addKeySubGraph (MapPersistentAttribute <? super J , ? super AJ , ?> attribute , ManagedDomainType <AJ > subtype ) {
281317 return findOrCreateAttributeNode ( attribute ).makeKeySubGraph ( subtype );
282318 }
283319
@@ -328,13 +364,38 @@ public <E> SubGraphImplementor<E> addTreatedElementSubgraph(
328364 }
329365
330366 @ Override
331- public <S extends J > SubGraphImplementor <S > addTreatedSubGraph (Class <S > type ) {
332- final ManagedDomainType <S > managedDomainType = getGraphedType ().getMetamodel ().managedType ( type );
333- final SubGraphImpl <S > subgraph = new SubGraphImpl <>( managedDomainType , this , true );
334- if ( subgraphs == null ) {
335- subgraphs = new ArrayList <>( 1 );
367+ public <S extends J > SubGraphImplementor <S > addTreatedSubGraph (ManagedDomainType <S > type ) {
368+ final Class <S > javaType = type .getJavaType ();
369+ final SubGraphImplementor <S > castSubgraph = subgraph ( javaType );
370+ if ( castSubgraph == null ) {
371+ final SubGraphImpl <S > subgraph = new SubGraphImpl <>( type , true );
372+ subgraphs .put ( javaType , subgraph );
373+ return subgraph ;
336374 }
337- subgraphs .add ( subgraph );
338- return subgraph ;
375+ else {
376+ return castSubgraph ;
377+ }
378+ }
379+
380+ private <S extends J > SubGraphImplementor <S > subgraph (Class <S > javaType ) {
381+ final SubGraphImplementor <?> existing = subgraphs .get ( javaType );
382+ if ( existing != null ) {
383+ @ SuppressWarnings ("unchecked" )
384+ final SubGraphImplementor <S > castSubgraph = (SubGraphImplementor <S >) existing ;
385+ return castSubgraph ;
386+ }
387+ else {
388+ return null ;
389+ }
390+ }
391+
392+ @ Override
393+ public <S extends J > SubGraphImplementor <S > addTreatedSubGraph (Class <S > type ) {
394+ return addTreatedSubGraph ( getGraphedType ().getMetamodel ().managedType ( type ) );
395+ }
396+
397+ @ Override
398+ public Map <Class <?>, SubGraphImplementor <?>> getSubGraphMap () {
399+ return subgraphs ;
339400 }
340401}
0 commit comments