From 24fe60e1560c6eb43051aa7bcac93ce2df6dc41d Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 2 Jan 2025 05:34:44 +0100 Subject: [PATCH] Graphpocalypse: major revision/refactoring of EntityGraph support - important simplification --- .../org/hibernate/graph/AttributeNode.java | 7 +- .../org/hibernate/graph/EntityGraphs.java | 1 - .../main/java/org/hibernate/graph/Graph.java | 19 +- .../graph/internal/AbstractGraph.java | 120 ++++++-- .../graph/internal/AttributeNodeImpl.java | 273 +++++++++--------- .../graph/internal/SubGraphImpl.java | 4 - .../graph/spi/AttributeNodeImplementor.java | 53 ++-- .../hibernate/graph/spi/GraphImplementor.java | 17 +- .../orm/test/graph/EntityGraphsTest.java | 2 +- 9 files changed, 285 insertions(+), 211 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/graph/AttributeNode.java b/hibernate-core/src/main/java/org/hibernate/graph/AttributeNode.java index 7029e08027..da3daa569c 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/AttributeNode.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/AttributeNode.java @@ -4,11 +4,12 @@ */ package org.hibernate.graph; -import java.util.Map; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; +import java.util.Map; + /** * Extends the JPA-defined {@link AttributeNode} with additional operations. * @@ -26,8 +27,8 @@ public interface AttributeNode extends GraphNode, jakarta.persistence.Attr SubGraph makeSubGraph(); SubGraph makeKeySubGraph(); - SubGraph makeSubGraph(Class type); - SubGraph makeKeySubGraph(Class type); + SubGraph makeSubGraph(Class subtype); + SubGraph makeKeySubGraph(Class subtype); SubGraph makeSubGraph(ManagedDomainType subtype); SubGraph makeKeySubGraph(ManagedDomainType subtype); diff --git a/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java b/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java index b1891aee19..021b2d5a5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java @@ -61,7 +61,6 @@ public final class EntityGraphs { for ( jakarta.persistence.Graph graph : graphs ) { merged.merge( (GraphImplementor) graph ); } - } return merged; } diff --git a/hibernate-core/src/main/java/org/hibernate/graph/Graph.java b/hibernate-core/src/main/java/org/hibernate/graph/Graph.java index d41953ca8b..f0bc73fa67 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/Graph.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/Graph.java @@ -11,6 +11,7 @@ import jakarta.persistence.metamodel.PluralAttribute; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PersistentAttribute; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; /** * A container for {@link AttributeNode} references. @@ -130,6 +131,8 @@ public interface Graph extends GraphNode, jakarta.persistence.Graph { SubGraph addTreatedSubGraph(Class type); + SubGraph addTreatedSubGraph(ManagedDomainType type); + /** * Create and return a new (mutable) {@link SubGraph} associated with * the named {@link AttributeNode}. @@ -151,18 +154,22 @@ public interface Graph extends GraphNode, jakarta.persistence.Graph { SubGraph addSubGraph(PersistentAttribute attribute, Class type); - SubGraph addSubGraph(MapPersistentAttribute attribute, ManagedDomainType type); + SubGraph addSubGraph(PersistentAttribute attribute, ManagedDomainType type); + + SubGraph addElementSubGraph(PluralPersistentAttribute attribute, Class type); + + SubGraph addElementSubGraph(PluralPersistentAttribute attribute, ManagedDomainType type); @Deprecated SubGraph addKeySubGraph(String attributeName); SubGraph addKeySubGraph(String attributeName, Class type); - SubGraph addKeySubGraph(PersistentAttribute attribute, ManagedDomainType type); + SubGraph addKeySubGraph(MapPersistentAttribute attribute, ManagedDomainType type); @Override default SubGraph addTreatedSubgraph(Attribute attribute, Class type) { - return addSubGraph( (PersistentAttribute) attribute, type ); + return addSubGraph( (PersistentAttribute) attribute ).addTreatedSubGraph( type ); } @Override @@ -172,7 +179,7 @@ public interface Graph extends GraphNode, jakarta.persistence.Graph { @Override default SubGraph addSubgraph(Attribute attribute, Class type) { - return addSubGraph( (PersistentAttribute) attribute, type ); + return addSubGraph( (PersistentAttribute) attribute ).addTreatedSubGraph( type ); } @Override @@ -182,7 +189,7 @@ public interface Graph extends GraphNode, jakarta.persistence.Graph { @Override default SubGraph addSubgraph(String name, Class type) { - return addSubGraph( name, type ); + return addSubGraph( name ).addTreatedSubGraph( type ); } @Override @@ -192,7 +199,7 @@ public interface Graph extends GraphNode, jakarta.persistence.Graph { @Override default SubGraph addKeySubgraph(String name, Class type) { - return addKeySubGraph( name, type ); + return addKeySubGraph( name ).addTreatedSubGraph( type ); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/graph/internal/AbstractGraph.java b/hibernate-core/src/main/java/org/hibernate/graph/internal/AbstractGraph.java index b89414221e..9bf8dc5513 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/internal/AbstractGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/internal/AbstractGraph.java @@ -23,6 +23,7 @@ import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PersistentAttribute; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.sqm.SqmPathSource; import jakarta.persistence.metamodel.Attribute; @@ -39,8 +40,8 @@ import static java.util.Collections.unmodifiableMap; public abstract class AbstractGraph extends AbstractGraphNode implements GraphImplementor { private final ManagedDomainType managedType; + private final Map, SubGraphImplementor> subgraphs = new HashMap<>(1); private Map, AttributeNodeImplementor> attributeNodes; - private List> subgraphs; public AbstractGraph(ManagedDomainType managedType, boolean mutable) { super( mutable ); @@ -50,8 +51,7 @@ public abstract class AbstractGraph extends AbstractGraphNode implements G protected AbstractGraph(ManagedDomainType managedType, GraphImplementor graph, boolean mutable) { this( managedType, mutable ); attributeNodes = new HashMap<>( graph.getAttributeNodesByAttribute().size() ); - graph.getAttributeNodesByAttribute() - .forEach( (attribute, node) -> attributeNodes.put( attribute, node.makeCopy( mutable ) ) ); + mergeInternal( graph, mutable ); } protected AbstractGraph(GraphImplementor graph, boolean mutable) { @@ -76,42 +76,61 @@ public abstract class AbstractGraph extends AbstractGraphNode implements G } @Override - public void merge(GraphImplementor graph) { + public void merge(GraphImplementor graph) { + merge( graph, true ); + } + + @Override + public void merge(GraphImplementor graph, boolean mutable) { if ( graph != null ) { verifyMutability(); - graph.getAttributeNodesByAttribute().forEach( (attribute, node) -> { - final AttributeNodeImplementor existingNode = findAttributeNode( attribute ); - if ( existingNode != null ) { - // keep the local one, but merge in the incoming one - mergeNode( node, existingNode ); - } - else { - addAttributeNode( attribute, node.makeCopy( true ) ); - } - } ); + mergeInternal( graph, mutable ); } } - private static void mergeNode(AttributeNodeImplementor node, AttributeNodeImplementor existingNode) { + private void mergeInternal(GraphImplementor graph, boolean mutable) { + graph.getAttributeNodesByAttribute().forEach( (attribute, node) -> { + final AttributeNodeImplementor existingNode = findAttributeNode( attribute ); + if ( existingNode != null ) { + // keep the local one, but merge in the incoming one + mergeNode( node, existingNode, mutable ); + } + else { + addAttributeNode( attribute, node.makeCopy( mutable ), mutable ); + } + } ); + graph.getSubGraphMap().forEach( (type, subgraph) -> { + final SubGraphImplementor existing = subgraphs.get( type ); + if ( existing != null ) { + existing.merge( (SubGraphImplementor) subgraph, mutable ); + } + else { + subgraphs.put( type, subgraph.makeCopy( mutable ) ); + } + } ); + } + + private static void mergeNode( + AttributeNodeImplementor node, AttributeNodeImplementor existingNode, boolean mutable) { if ( existingNode.getAttributeDescriptor() == node.getAttributeDescriptor() ) { @SuppressWarnings("unchecked") // safe, we just checked final AttributeNodeImplementor castNode = (AttributeNodeImplementor) node; - existingNode.merge( castNode ); + existingNode.merge( castNode, mutable ); } else { throw new AssertionFailure( "Attributes should have been identical" ); } } - private void addAttributeNode(PersistentAttribute attribute, AttributeNodeImplementor node) { + private void addAttributeNode( + PersistentAttribute attribute, AttributeNodeImplementor node, boolean mutable) { final AttributeNodeImplementor attributeNode = getNodeForPut( node.getAttributeDescriptor() ); if ( attributeNode == null ) { attributeNodes.put( attribute, node ); } else { // we assume the subgraph has been properly copied if needed - node.getSubGraphMap().forEach( (subtype, subgraph) -> attributeNode.addSubGraph( subgraph ) ); - node.getKeySubGraphMap().forEach( (subtype, subgraph) -> attributeNode.addKeySubGraph( subgraph ) ); + node.merge( attributeNode, mutable ); } } @@ -126,8 +145,8 @@ public abstract class AbstractGraph extends AbstractGraphNode implements G @SuppressWarnings("unchecked") // The JPA API is unsafe by nature final PersistentAttribute persistentAttribute = (PersistentAttribute) attribute; final AttributeNodeImplementor node = attribute == null ? null : findAttributeNode( persistentAttribute ); - if ( node == null && subgraphs != null ) { - for ( SubGraphImplementor subgraph : subgraphs ) { + if ( node == null ) { + for ( SubGraphImplementor subgraph : subgraphs.values() ) { final AttributeNodeImplementor subgraphNode = subgraph.findAttributeNode( attributeName ); if ( subgraphNode != null ) { return subgraphNode; @@ -272,12 +291,22 @@ public abstract class AbstractGraph extends AbstractGraphNode implements G } @Override - public SubGraphImplementor addSubGraph(MapPersistentAttribute attribute, ManagedDomainType subtype) { + public SubGraphImplementor addSubGraph(PersistentAttribute attribute, ManagedDomainType subtype) { return findOrCreateAttributeNode( attribute ).makeSubGraph( subtype ); } @Override - public SubGraphImplementor addKeySubGraph(PersistentAttribute attribute, ManagedDomainType subtype) { + public SubGraphImplementor addElementSubGraph(PluralPersistentAttribute attribute, Class type) { + return findOrCreateAttributeNode( attribute ).makeSubGraph( type ); + } + + @Override + public SubGraphImplementor addElementSubGraph(PluralPersistentAttribute attribute, ManagedDomainType type) { + return findOrCreateAttributeNode( attribute ).makeSubGraph( type ); + } + + @Override + public SubGraphImplementor addKeySubGraph(MapPersistentAttribute attribute, ManagedDomainType subtype) { return findOrCreateAttributeNode( attribute ).makeKeySubGraph( subtype ); } @@ -328,13 +357,44 @@ public abstract class AbstractGraph extends AbstractGraphNode implements G } @Override - public SubGraphImplementor addTreatedSubGraph(Class type) { - final ManagedDomainType managedDomainType = getGraphedType().getMetamodel().managedType( type ); - final SubGraphImpl subgraph = new SubGraphImpl<>( managedDomainType, this, true ); - if ( subgraphs == null ) { - subgraphs = new ArrayList<>( 1 ); + public SubGraphImplementor addTreatedSubGraph(ManagedDomainType type) { + if ( getGraphedType().equals( type ) ) { + //noinspection unchecked + return (SubGraphImplementor) this; } - subgraphs.add( subgraph ); - return subgraph; + else { + final Class javaType = type.getJavaType(); + final SubGraphImplementor castSubgraph = subgraph( javaType ); + if ( castSubgraph == null ) { + final SubGraphImpl subgraph = new SubGraphImpl<>( type, true ); + subgraphs.put( javaType, subgraph ); + return subgraph; + } + else { + return castSubgraph; + } + } + } + + private SubGraphImplementor subgraph(Class javaType) { + final SubGraphImplementor existing = subgraphs.get( javaType ); + if ( existing != null ) { + @SuppressWarnings("unchecked") + final SubGraphImplementor castSubgraph = (SubGraphImplementor) existing; + return castSubgraph; + } + else { + return null; + } + } + + @Override + public SubGraphImplementor addTreatedSubGraph(Class type) { + return addTreatedSubGraph( getGraphedType().getMetamodel().managedType( type ) ); + } + + @Override + public Map, SubGraphImplementor> getSubGraphMap() { + return subgraphs; } } diff --git a/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java b/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java index 400ac0690d..6784c30cc8 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java @@ -4,16 +4,19 @@ */ package org.hibernate.graph.internal; -import java.util.HashMap; -import java.util.Map; - +import jakarta.persistence.Subgraph; import org.hibernate.graph.spi.AttributeNodeImplementor; import org.hibernate.graph.spi.SubGraphImplementor; +import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; +import java.util.HashMap; +import java.util.Map; + import static java.util.Collections.emptyMap; + /** * Implementation of {@link jakarta.persistence.AttributeNode}. * @@ -24,25 +27,23 @@ public class AttributeNodeImpl implements AttributeNodeImplementor { private final PersistentAttribute attribute; - private Map, SubGraphImplementor> subgraphMap; - private Map, SubGraphImplementor> keySubgraphMap; + private SubGraphImplementor subgraph; + private SubGraphImplementor keySubgraph; public AttributeNodeImpl(PersistentAttribute attribute, boolean mutable) { - this(attribute, null, null, mutable); + this(attribute, mutable, null, null); } /** * Intended only for use from making a copy */ private AttributeNodeImpl( - PersistentAttribute attribute, - Map, SubGraphImplementor> subgraphMap, - Map, SubGraphImplementor> keySubgraphMap, - boolean mutable) { + PersistentAttribute attribute, boolean mutable, + SubGraphImplementor subgraph, SubGraphImplementor keySubgraph) { super( mutable ); this.attribute = attribute; - this.subgraphMap = subgraphMap; - this.keySubgraphMap = keySubgraphMap; + this.subgraph = subgraph; + this.keySubgraph = keySubgraph; } @Override @@ -56,191 +57,203 @@ public class AttributeNodeImpl } @Override - public Map, SubGraphImplementor> getSubGraphMap() { - return subgraphMap == null ? emptyMap() : subgraphMap; + public SubGraphImplementor getSubGraph() { + return subgraph; } @Override - public Map, SubGraphImplementor> getKeySubGraphMap() { - return keySubgraphMap == null ? emptyMap() : keySubgraphMap; + public SubGraphImplementor getKeySubGraph() { + return keySubgraph; + } + + private SubGraphImplementor subgraph(ManagedDomainType valueType) { + if ( subgraph == null ) { + final SubGraphImplementor graph = new SubGraphImpl<>( valueType, true ); + subgraph = graph; + return graph; + } + else { + //noinspection unchecked + return (SubGraphImplementor) subgraph; + } } @Override public SubGraphImplementor makeSubGraph() { - return makeSubGraph( (ManagedDomainType) attribute.getValueGraphType() ); + verifyMutability(); + return subgraph( (ManagedDomainType) attribute.getValueGraphType() ); } @Override - public SubGraphImplementor makeSubGraph(Class type) { - return makeSubGraph( attribute.getDeclaringType().getMetamodel().managedType( type ) ); + public SubGraphImplementor makeSubGraph(Class subtype) { + verifyMutability(); + final DomainType type = attribute.getValueGraphType(); + if ( !type.getBindableJavaType().isAssignableFrom( subtype ) ) { + throw new IllegalArgumentException( "Not a subtype: " + subtype.getName() ); + } + @SuppressWarnings("unchecked") + final ManagedDomainType valueType = (ManagedDomainType) type; + SubGraphImplementor subgraph = subgraph( valueType ); + if ( type.getBindableJavaType() == subtype ) { + //noinspection unchecked + return (SubGraphImplementor) subgraph; + } + else { + return subgraph.addTreatedSubGraph( subtype ); + } } @Override public SubGraphImplementor makeSubGraph(ManagedDomainType subtype) { verifyMutability(); - assert subtype != null; - final Class javaType = subtype.getJavaType(); - if ( !attribute.getValueGraphType().getBindableJavaType().isAssignableFrom( javaType ) ) { + final DomainType type = attribute.getValueGraphType(); + final Class javaType = subtype.getBindableJavaType(); + if ( !type.getBindableJavaType().isAssignableFrom( javaType ) ) { throw new IllegalArgumentException( "Not a subtype: " + javaType.getName() ); } - final SubGraphImplementor existing = subgraphMap == null ? null : getSubgraph( javaType ); - if ( existing != null ) { - return existing; + @SuppressWarnings("unchecked") + final ManagedDomainType valueType = (ManagedDomainType) type; + SubGraphImplementor subgraph = subgraph( valueType ); + if ( type.getBindableJavaType() == javaType ) { + //noinspection unchecked + return (SubGraphImplementor) subgraph; } else { - final SubGraphImplementor subGraph = new SubGraphImpl<>( subtype, true ); - addSubGraph( subGraph ); - return subGraph; + return subgraph.addTreatedSubGraph( subtype ); } } - @Override - public void addSubGraph(SubGraphImplementor subgraph) { - addSubgraph( subgraph ); - } - - private void addSubgraph(SubGraphImplementor subgraph) { - if ( subgraphMap == null ) { - subgraphMap = new HashMap<>(); - subgraphMap.put( subgraph.getClassType(), subgraph ); + private SubGraphImplementor keySubgraph(ManagedDomainType keyType) { + if ( keySubgraph == null ) { + final SubGraphImplementor graph = new SubGraphImpl<>( keyType, true ); + keySubgraph = graph; + return graph; } else { - final SubGraphImplementor existing = getSubgraph( subgraph.getClassType() ); - if ( existing == null ) { - subgraphMap.put( subgraph.getClassType(), subgraph ); - } - else { - existing.merge( subgraph ); - } - } - } - - @Override - public void addKeySubGraph(SubGraphImplementor subgraph) { - addKeySubgraph( subgraph ); - } - - private void addKeySubgraph(SubGraphImplementor subgraph) { - if ( keySubgraphMap == null ) { - keySubgraphMap = new HashMap<>(); - keySubgraphMap.put( subgraph.getClassType(), subgraph ); - } - else { - final SubGraphImplementor existing = getKeySubgraph( subgraph.getClassType() ); - if ( existing == null ) { - keySubgraphMap.put( subgraph.getClassType(), subgraph ); - } - else { - existing.merge( subgraph ); - } + //noinspection unchecked + return (SubGraphImplementor) keySubgraph; } } @Override public SubGraphImplementor makeKeySubGraph() { - return makeKeySubGraph( (ManagedDomainType) attribute.getKeyGraphType() ); + verifyMutability(); + return keySubgraph( (ManagedDomainType) attribute.getKeyGraphType() ); } @Override - public SubGraphImplementor makeKeySubGraph(Class type) { - return makeKeySubGraph( attribute.getDeclaringType().getMetamodel().managedType( type ) ); + public SubGraphImplementor makeKeySubGraph(Class subtype) { + verifyMutability(); + final DomainType type = attribute.getKeyGraphType(); + if ( !type.getBindableJavaType().isAssignableFrom( subtype ) ) { + throw new IllegalArgumentException( "Not a key subtype: " + subtype.getName() ); + } + @SuppressWarnings("unchecked") + final ManagedDomainType keyType = (ManagedDomainType) type; + final SubGraphImplementor keySubgraph = keySubgraph( keyType ); + if ( type.getBindableJavaType() == subtype ) { + //noinspection unchecked + return (SubGraphImplementor) keySubgraph; + } + else { + return keySubgraph.addTreatedSubGraph( subtype ); + } } @Override public SubGraphImplementor makeKeySubGraph(ManagedDomainType subtype) { verifyMutability(); - assert subtype != null; - final Class javaType = subtype.getJavaType(); - if ( !attribute.getKeyGraphType().getBindableJavaType().isAssignableFrom( javaType ) ) { + final DomainType type = attribute.getKeyGraphType(); + final Class javaType = subtype.getBindableJavaType(); + if ( !type.getBindableJavaType().isAssignableFrom( javaType ) ) { throw new IllegalArgumentException( "Not a key subtype: " + javaType.getName() ); } - final SubGraphImplementor existing = keySubgraphMap == null ? null : getKeySubgraph( javaType ); - if ( existing != null ) { - return existing; + @SuppressWarnings("unchecked") + final ManagedDomainType keyType = (ManagedDomainType) type; + final SubGraphImplementor keySubgraph = keySubgraph( keyType ); + if ( type.getBindableJavaType() == javaType ) { + //noinspection unchecked + return (SubGraphImplementor) keySubgraph; } else { - final SubGraphImplementor subgraph = new SubGraphImpl<>( subtype, true ); - addKeySubGraph( subgraph ); - return subgraph; + return keySubgraph.addTreatedSubGraph( subtype ); } } @Override public AttributeNodeImplementor makeCopy(boolean mutable) { - return new AttributeNodeImpl<>( - this.attribute, - makeMapCopy( mutable, subgraphMap ), - makeMapCopy( mutable, keySubgraphMap ), - mutable - ); + return new AttributeNodeImpl<>( this.attribute, mutable, + subgraph == null ? null : subgraph.makeCopy( mutable ), + keySubgraph == null ? null : keySubgraph.makeCopy( mutable ) ); } - private Map, SubGraphImplementor> makeMapCopy( - boolean mutable, - Map, SubGraphImplementor> nodeMap) { - if ( nodeMap == null ) { - return null; + @Override + public void merge(AttributeNodeImplementor other, boolean mutable) { + final SubGraphImplementor otherSubgraph = other.getSubGraph(); + if ( otherSubgraph != null ) { + if ( subgraph == null ) { + subgraph = otherSubgraph.makeCopy( mutable ); + } + else { + subgraph.merge( (SubGraphImplementor) otherSubgraph, mutable ); + } + } + final SubGraphImplementor otherKeySubgraph = other.getKeySubGraph(); + if ( otherKeySubgraph != null ) { + if ( keySubgraph == null ) { + keySubgraph = otherKeySubgraph.makeCopy( mutable ); + } + else { + keySubgraph.merge( (SubGraphImplementor) otherKeySubgraph, mutable ); + } + } + } + + @Override + public Map, SubGraphImplementor> getSubGraphMap() { + if ( subgraph == null ) { + return emptyMap(); } else { - final HashMap, SubGraphImplementor> map = new HashMap<>( nodeMap.size() ); - nodeMap.forEach( (attribute, subgraph) -> map.put( attribute, subgraph.makeCopy( mutable ) ) ); + final HashMap, SubGraphImplementor> map = new HashMap<>( subgraph.getSubGraphMap() ); + map.put( attribute.getValueGraphType().getBindableJavaType(), subgraph ); return map; } } @Override - public void merge(AttributeNodeImplementor other) { - other.getSubGraphMap().values().forEach( this::mergeToSubgraph ); - other.getKeySubGraphMap().values().forEach( this::mergeToKeySubgraph ); - } - - private void mergeToKeySubgraph(SubGraphImplementor subgraph) { - final SubGraphImplementor existing = getKeySubgraphForPut( subgraph ); - if ( existing != null ) { - existing.merge( subgraph ); + public Map, SubGraphImplementor> getKeySubGraphMap() { + if ( keySubgraph == null ) { + return emptyMap(); } else { - addKeySubGraph( subgraph.makeCopy( true ) ); + final HashMap, SubGraphImplementor> map = new HashMap<>( keySubgraph.getSubGraphMap() ); + map.put( attribute.getKeyGraphType().getJavaType(), keySubgraph ); + return map; } } - private void mergeToSubgraph(SubGraphImplementor subgraph) { - final SubGraphImplementor existing = getSubgraphForPut( subgraph ); - if ( existing != null ) { - existing.merge( subgraph ); + @Override + public @SuppressWarnings("rawtypes") Map getSubgraphs() { + if ( subgraph == null ) { + return emptyMap(); } else { - addSubGraph( subgraph.makeCopy( true ) ); + final HashMap map = new HashMap<>( subgraph.getSubGraphMap() ); + map.put( attribute.getValueGraphType().getBindableJavaType(), subgraph ); + return map; } } - private SubGraphImplementor getSubgraphForPut(SubGraphImplementor subgraph) { - if ( subgraphMap == null ) { - subgraphMap = new HashMap<>(); - return null; + @Override + public @SuppressWarnings("rawtypes") Map getKeySubgraphs() { + if ( keySubgraph == null ) { + return emptyMap(); } else { - return getSubgraph( subgraph.getClassType() ); + final HashMap map = new HashMap<>( keySubgraph.getSubGraphMap() ); + map.put( attribute.getKeyGraphType().getJavaType(), keySubgraph ); + return map; } } - - private SubGraphImplementor getKeySubgraphForPut(SubGraphImplementor subgraph) { - if ( keySubgraphMap == null ) { - keySubgraphMap = new HashMap<>(); - return null; - } - else { - return getKeySubgraph( subgraph.getClassType() ); - } - } - - @SuppressWarnings("unchecked") - private SubGraphImplementor getSubgraph(Class incomingSubtype) { - return (SubGraphImplementor) subgraphMap.get( incomingSubtype ); - } - - @SuppressWarnings("unchecked") - private SubGraphImplementor getKeySubgraph(Class incomingSubtype) { - return (SubGraphImplementor) keySubgraphMap.get( incomingSubtype ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/graph/internal/SubGraphImpl.java b/hibernate-core/src/main/java/org/hibernate/graph/internal/SubGraphImpl.java index 85eae4725a..1e2f24537b 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/internal/SubGraphImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/internal/SubGraphImpl.java @@ -22,10 +22,6 @@ public class SubGraphImpl extends AbstractGraph implements SubGraphImpleme super( original, mutable ); } - public SubGraphImpl(ManagedDomainType managedDomainType, AbstractGraph original, boolean mutable) { - super( managedDomainType, original, mutable ); - } - @Override public SubGraphImplementor makeCopy(boolean mutable) { return new SubGraphImpl<>( this, mutable ); diff --git a/hibernate-core/src/main/java/org/hibernate/graph/spi/AttributeNodeImplementor.java b/hibernate-core/src/main/java/org/hibernate/graph/spi/AttributeNodeImplementor.java index e9bf2b2f03..1a1d66b728 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/spi/AttributeNodeImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/spi/AttributeNodeImplementor.java @@ -4,15 +4,11 @@ */ package org.hibernate.graph.spi; -import java.util.Map; - -import jakarta.persistence.Subgraph; - import org.hibernate.graph.AttributeNode; import org.hibernate.graph.SubGraph; import org.hibernate.metamodel.model.domain.ManagedDomainType; -import static java.util.Collections.unmodifiableMap; +import java.util.Map; /** * Integration version of the {@link AttributeNode} contract @@ -22,29 +18,6 @@ import static java.util.Collections.unmodifiableMap; */ public interface AttributeNodeImplementor extends AttributeNode, GraphNodeImplementor { - Map, SubGraphImplementor> getSubGraphMap(); - Map, SubGraphImplementor> getKeySubGraphMap(); - - @Override - default Map, ? extends SubGraph> getSubGraphs() { - return unmodifiableMap( getSubGraphMap() ); - } - - @Override - default Map, ? extends SubGraph> getKeySubGraphs() { - return unmodifiableMap( getKeySubGraphMap() ); - } - - @Override // JPA API uses raw types - default @SuppressWarnings("rawtypes") Map getSubgraphs() { - return unmodifiableMap( getSubGraphMap() ); - } - - @Override // JPA API uses raw types - default @SuppressWarnings("rawtypes") Map getKeySubgraphs() { - return unmodifiableMap( getKeySubGraphMap() ); - } - @Override AttributeNodeImplementor makeCopy(boolean mutable); @@ -55,10 +28,10 @@ public interface AttributeNodeImplementor extends AttributeNode, GraphNode SubGraphImplementor makeKeySubGraph(); @Override - SubGraphImplementor makeSubGraph(Class type); + SubGraphImplementor makeSubGraph(Class subtype); @Override - SubGraphImplementor makeKeySubGraph(Class type); + SubGraphImplementor makeKeySubGraph(Class subtype); @Override SubGraphImplementor makeSubGraph(ManagedDomainType subtype); @@ -66,9 +39,23 @@ public interface AttributeNodeImplementor extends AttributeNode, GraphNode @Override SubGraphImplementor makeKeySubGraph(ManagedDomainType subtype); - void merge(AttributeNodeImplementor other); + void merge(AttributeNodeImplementor other, boolean mutable); - void addSubGraph(SubGraphImplementor subgraph); + SubGraphImplementor getSubGraph(); - void addKeySubGraph(SubGraphImplementor subgraph); + SubGraphImplementor getKeySubGraph(); + + Map, SubGraphImplementor> getSubGraphMap(); + + Map, SubGraphImplementor> getKeySubGraphMap(); + + @Override + default Map, ? extends SubGraph> getSubGraphs() { + return getSubGraphMap(); + } + + @Override + default Map, ? extends SubGraph> getKeySubGraphs() { + return getKeySubGraphMap(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphImplementor.java b/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphImplementor.java index 989536f121..81afe4cf58 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/spi/GraphImplementor.java @@ -12,6 +12,7 @@ import org.hibernate.graph.Graph; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PersistentAttribute; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; /** @@ -23,7 +24,9 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute; */ public interface GraphImplementor extends Graph, GraphNodeImplementor { - void merge(GraphImplementor other); + void merge(GraphImplementor other); + + void merge(GraphImplementor other, boolean mutable); @Override @Deprecated(forRemoval = true) RootGraphImplementor makeRootGraph(String name, boolean mutable) @@ -72,11 +75,19 @@ public interface GraphImplementor extends Graph, GraphNodeImplementor { SubGraphImplementor addKeySubGraph(String attributeName, Class subtype); @Override - SubGraphImplementor addSubGraph(MapPersistentAttribute attribute, ManagedDomainType subtype); + SubGraphImplementor addSubGraph(PersistentAttribute attribute, ManagedDomainType subtype); + + SubGraphImplementor addElementSubGraph(PluralPersistentAttribute attribute, Class type); + + SubGraphImplementor addElementSubGraph(PluralPersistentAttribute attribute, ManagedDomainType type); @Override - SubGraphImplementor addKeySubGraph(PersistentAttribute attribute, ManagedDomainType subtype); + SubGraphImplementor addKeySubGraph(MapPersistentAttribute attribute, ManagedDomainType subtype); @Override SubGraphImplementor addTreatedSubGraph(Class type); + + SubGraphImplementor addTreatedSubGraph(ManagedDomainType type); + + Map, SubGraphImplementor> getSubGraphMap(); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/graph/EntityGraphsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/graph/EntityGraphsTest.java index 7e73ad0720..db1bbd8b8e 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/graph/EntityGraphsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/graph/EntityGraphsTest.java @@ -25,7 +25,7 @@ public class EntityGraphsTest extends AbstractEntityGraphTest { } @SafeVarargs - private final void checkMerge(EntityGraph expected, EntityGraph... graphs) { + private void checkMerge(EntityGraph expected, EntityGraph... graphs) { checkMerge( GraphParsingTestEntity.class, expected, graphs ); }