Graphpocalypse: major revision/refactoring of EntityGraph support

- important simplification
This commit is contained in:
Gavin King 2025-01-02 05:34:44 +01:00
parent 5687749fec
commit 24fe60e156
9 changed files with 285 additions and 211 deletions

View File

@ -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<J> extends GraphNode<J>, jakarta.persistence.Attr
SubGraph<?> makeSubGraph();
SubGraph<?> makeKeySubGraph();
<S> SubGraph<S> makeSubGraph(Class<S> type);
<S> SubGraph<S> makeKeySubGraph(Class<S> type);
<S> SubGraph<S> makeSubGraph(Class<S> subtype);
<S> SubGraph<S> makeKeySubGraph(Class<S> subtype);
<S> SubGraph<S> makeSubGraph(ManagedDomainType<S> subtype);
<S> SubGraph<S> makeKeySubGraph(ManagedDomainType<S> subtype);

View File

@ -61,7 +61,6 @@ public final class EntityGraphs {
for ( jakarta.persistence.Graph<T> graph : graphs ) {
merged.merge( (GraphImplementor<T>) graph );
}
}
return merged;
}

View File

@ -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<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {
<Y extends J> SubGraph<Y> addTreatedSubGraph(Class<Y> type);
<Y extends J> SubGraph<Y> addTreatedSubGraph(ManagedDomainType<Y> type);
/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the named {@link AttributeNode}.
@ -151,18 +154,22 @@ public interface Graph<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {
<AJ> SubGraph<AJ> addSubGraph(PersistentAttribute<? super J, ? super AJ> attribute, Class<AJ> type);
<AJ> SubGraph<AJ> addSubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> type);
<AJ> SubGraph<AJ> addSubGraph(PersistentAttribute<? super J, ? super AJ> attribute, ManagedDomainType<AJ> type);
<AJ> SubGraph<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, Class<AJ> type);
<AJ> SubGraph<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, ManagedDomainType<AJ> type);
@Deprecated
<AJ> SubGraph<AJ> addKeySubGraph(String attributeName);
<AJ> SubGraph<AJ> addKeySubGraph(String attributeName, Class<AJ> type);
<AJ> SubGraph<AJ> addKeySubGraph(PersistentAttribute<? super J, ? super AJ> attribute, ManagedDomainType<AJ> type);
<AJ> SubGraph<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> type);
@Override
default <Y> SubGraph<Y> addTreatedSubgraph(Attribute<? super J, ? super Y> attribute, Class<Y> type) {
return addSubGraph( (PersistentAttribute<? super J, ? super Y>) attribute, type );
return addSubGraph( (PersistentAttribute<? super J, ? super Y>) attribute ).addTreatedSubGraph( type );
}
@Override
@ -172,7 +179,7 @@ public interface Graph<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {
@Override
default <X> SubGraph<? extends X> addSubgraph(Attribute<? super J, X> attribute, Class<? extends X> type) {
return addSubGraph( (PersistentAttribute<? super J, X>) attribute, type );
return addSubGraph( (PersistentAttribute<? super J, X>) attribute ).addTreatedSubGraph( type );
}
@Override
@ -182,7 +189,7 @@ public interface Graph<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {
@Override
default <X> SubGraph<X> addSubgraph(String name, Class<X> type) {
return addSubGraph( name, type );
return addSubGraph( name ).addTreatedSubGraph( type );
}
@Override
@ -192,7 +199,7 @@ public interface Graph<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {
@Override
default <X> SubGraph<X> addKeySubgraph(String name, Class<X> type) {
return addKeySubGraph( name, type );
return addKeySubGraph( name ).addTreatedSubGraph( type );
}
/**

View File

@ -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<J> extends AbstractGraphNode<J> implements GraphImplementor<J> {
private final ManagedDomainType<J> managedType;
private final Map<Class<?>, SubGraphImplementor<?>> subgraphs = new HashMap<>(1);
private Map<PersistentAttribute<? super J,?>, AttributeNodeImplementor<?>> attributeNodes;
private List<SubGraphImplementor<? extends J>> subgraphs;
public AbstractGraph(ManagedDomainType<J> managedType, boolean mutable) {
super( mutable );
@ -50,8 +51,7 @@ public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements G
protected AbstractGraph(ManagedDomainType<J> managedType, GraphImplementor<? super J> 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<J> graph, boolean mutable) {
@ -76,42 +76,61 @@ public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements G
}
@Override
public void merge(GraphImplementor<J> graph) {
public void merge(GraphImplementor<? super J> graph) {
merge( graph, true );
}
@Override
public void merge(GraphImplementor<? super J> graph, boolean mutable) {
if ( graph != null ) {
verifyMutability();
mergeInternal( graph, mutable );
}
}
private void mergeInternal(GraphImplementor<? super J> 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 );
mergeNode( node, existingNode, mutable );
}
else {
addAttributeNode( attribute, node.makeCopy( true ) );
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 <T> void mergeNode(AttributeNodeImplementor<?> node, AttributeNodeImplementor<T> existingNode) {
private static <T> void mergeNode(
AttributeNodeImplementor<?> node, AttributeNodeImplementor<T> existingNode, boolean mutable) {
if ( existingNode.getAttributeDescriptor() == node.getAttributeDescriptor() ) {
@SuppressWarnings("unchecked") // safe, we just checked
final AttributeNodeImplementor<T> castNode = (AttributeNodeImplementor<T>) node;
existingNode.merge( castNode );
existingNode.merge( castNode, mutable );
}
else {
throw new AssertionFailure( "Attributes should have been identical" );
}
}
private <T> void addAttributeNode(PersistentAttribute<? super J, ?> attribute, AttributeNodeImplementor<T> node) {
private <T> void addAttributeNode(
PersistentAttribute<? super J, ?> attribute, AttributeNodeImplementor<T> node, boolean mutable) {
final AttributeNodeImplementor<T> 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<J> extends AbstractGraphNode<J> implements G
@SuppressWarnings("unchecked") // The JPA API is unsafe by nature
final PersistentAttribute<? super J, AJ> persistentAttribute = (PersistentAttribute<? super J, AJ>) attribute;
final AttributeNodeImplementor<AJ> node = attribute == null ? null : findAttributeNode( persistentAttribute );
if ( node == null && subgraphs != null ) {
for ( SubGraphImplementor<? extends J> subgraph : subgraphs ) {
if ( node == null ) {
for ( SubGraphImplementor<?> subgraph : subgraphs.values() ) {
final AttributeNodeImplementor<AJ> subgraphNode = subgraph.findAttributeNode( attributeName );
if ( subgraphNode != null ) {
return subgraphNode;
@ -272,12 +291,22 @@ public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements G
}
@Override
public <AJ> SubGraphImplementor<AJ> addSubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> subtype) {
public <AJ> SubGraphImplementor<AJ> addSubGraph(PersistentAttribute<? super J, ? super AJ> attribute, ManagedDomainType<AJ> subtype) {
return findOrCreateAttributeNode( attribute ).makeSubGraph( subtype );
}
@Override
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(PersistentAttribute<? super J, ? super AJ> attribute, ManagedDomainType<AJ> subtype) {
public <AJ> SubGraphImplementor<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, Class<AJ> type) {
return findOrCreateAttributeNode( attribute ).makeSubGraph( type );
}
@Override
public <AJ> SubGraphImplementor<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, ManagedDomainType<AJ> type) {
return findOrCreateAttributeNode( attribute ).makeSubGraph( type );
}
@Override
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> subtype) {
return findOrCreateAttributeNode( attribute ).makeKeySubGraph( subtype );
}
@ -328,13 +357,44 @@ public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements G
}
@Override
public <S extends J> SubGraphImplementor<S> addTreatedSubGraph(Class<S> type) {
final ManagedDomainType<S> managedDomainType = getGraphedType().getMetamodel().managedType( type );
final SubGraphImpl<S> subgraph = new SubGraphImpl<>( managedDomainType, this, true );
if ( subgraphs == null ) {
subgraphs = new ArrayList<>( 1 );
public <S extends J> SubGraphImplementor<S> addTreatedSubGraph(ManagedDomainType<S> type) {
if ( getGraphedType().equals( type ) ) {
//noinspection unchecked
return (SubGraphImplementor<S>) this;
}
subgraphs.add( subgraph );
else {
final Class<S> javaType = type.getJavaType();
final SubGraphImplementor<S> castSubgraph = subgraph( javaType );
if ( castSubgraph == null ) {
final SubGraphImpl<S> subgraph = new SubGraphImpl<>( type, true );
subgraphs.put( javaType, subgraph );
return subgraph;
}
else {
return castSubgraph;
}
}
}
private <S extends J> SubGraphImplementor<S> subgraph(Class<S> javaType) {
final SubGraphImplementor<?> existing = subgraphs.get( javaType );
if ( existing != null ) {
@SuppressWarnings("unchecked")
final SubGraphImplementor<S> castSubgraph = (SubGraphImplementor<S>) existing;
return castSubgraph;
}
else {
return null;
}
}
@Override
public <S extends J> SubGraphImplementor<S> addTreatedSubGraph(Class<S> type) {
return addTreatedSubGraph( getGraphedType().getMetamodel().managedType( type ) );
}
@Override
public Map<Class<?>, SubGraphImplementor<?>> getSubGraphMap() {
return subgraphs;
}
}

View File

@ -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<J>
implements AttributeNodeImplementor<J> {
private final PersistentAttribute<?, J> attribute;
private Map<Class<?>, SubGraphImplementor<?>> subgraphMap;
private Map<Class<?>, SubGraphImplementor<?>> keySubgraphMap;
private SubGraphImplementor<?> subgraph;
private SubGraphImplementor<?> keySubgraph;
public <X> AttributeNodeImpl(PersistentAttribute<X, J> attribute, boolean mutable) {
this(attribute, null, null, mutable);
this(attribute, mutable, null, null);
}
/**
* Intended only for use from making a copy
*/
private AttributeNodeImpl(
PersistentAttribute<?, J> attribute,
Map<Class<?>, SubGraphImplementor<?>> subgraphMap,
Map<Class<?>, SubGraphImplementor<?>> keySubgraphMap,
boolean mutable) {
PersistentAttribute<?, J> 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<J>
}
@Override
public Map<Class<?>, SubGraphImplementor<?>> getSubGraphMap() {
return subgraphMap == null ? emptyMap() : subgraphMap;
public SubGraphImplementor<?> getSubGraph() {
return subgraph;
}
@Override
public Map<Class<?>, SubGraphImplementor<?>> getKeySubGraphMap() {
return keySubgraphMap == null ? emptyMap() : keySubgraphMap;
public SubGraphImplementor<?> getKeySubGraph() {
return keySubgraph;
}
private <T> SubGraphImplementor<T> subgraph(ManagedDomainType<T> valueType) {
if ( subgraph == null ) {
final SubGraphImplementor<T> graph = new SubGraphImpl<>( valueType, true );
subgraph = graph;
return graph;
}
else {
//noinspection unchecked
return (SubGraphImplementor<T>) subgraph;
}
}
@Override
public SubGraphImplementor<?> makeSubGraph() {
return makeSubGraph( (ManagedDomainType<?>) attribute.getValueGraphType() );
verifyMutability();
return subgraph( (ManagedDomainType<?>) attribute.getValueGraphType() );
}
@Override
public <S> SubGraphImplementor<S> makeSubGraph(Class<S> type) {
return makeSubGraph( attribute.getDeclaringType().getMetamodel().managedType( type ) );
public <S> SubGraphImplementor<S> makeSubGraph(Class<S> subtype) {
verifyMutability();
final DomainType<?> type = attribute.getValueGraphType();
if ( !type.getBindableJavaType().isAssignableFrom( subtype ) ) {
throw new IllegalArgumentException( "Not a subtype: " + subtype.getName() );
}
@SuppressWarnings("unchecked")
final ManagedDomainType<? super S> valueType = (ManagedDomainType<? super S>) type;
SubGraphImplementor<? super S> subgraph = subgraph( valueType );
if ( type.getBindableJavaType() == subtype ) {
//noinspection unchecked
return (SubGraphImplementor<S>) subgraph;
}
else {
return subgraph.addTreatedSubGraph( subtype );
}
}
@Override
public <S> SubGraphImplementor<S> makeSubGraph(ManagedDomainType<S> subtype) {
verifyMutability();
assert subtype != null;
final Class<S> javaType = subtype.getJavaType();
if ( !attribute.getValueGraphType().getBindableJavaType().isAssignableFrom( javaType ) ) {
final DomainType<?> type = attribute.getValueGraphType();
final Class<S> javaType = subtype.getBindableJavaType();
if ( !type.getBindableJavaType().isAssignableFrom( javaType ) ) {
throw new IllegalArgumentException( "Not a subtype: " + javaType.getName() );
}
final SubGraphImplementor<S> existing = subgraphMap == null ? null : getSubgraph( javaType );
if ( existing != null ) {
return existing;
@SuppressWarnings("unchecked")
final ManagedDomainType<? super S> valueType = (ManagedDomainType<? super S>) type;
SubGraphImplementor<? super S> subgraph = subgraph( valueType );
if ( type.getBindableJavaType() == javaType ) {
//noinspection unchecked
return (SubGraphImplementor<S>) subgraph;
}
else {
final SubGraphImplementor<S> subGraph = new SubGraphImpl<>( subtype, true );
addSubGraph( subGraph );
return subGraph;
return subgraph.addTreatedSubGraph( subtype );
}
}
@Override
public void addSubGraph(SubGraphImplementor<?> subgraph) {
addSubgraph( subgraph );
}
private <T> void addSubgraph(SubGraphImplementor<T> subgraph) {
if ( subgraphMap == null ) {
subgraphMap = new HashMap<>();
subgraphMap.put( subgraph.getClassType(), subgraph );
private <T> SubGraphImplementor<T> keySubgraph(ManagedDomainType<T> keyType) {
if ( keySubgraph == null ) {
final SubGraphImplementor<T> graph = new SubGraphImpl<>( keyType, true );
keySubgraph = graph;
return graph;
}
else {
final SubGraphImplementor<T> 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 <T> void addKeySubgraph(SubGraphImplementor<T> subgraph) {
if ( keySubgraphMap == null ) {
keySubgraphMap = new HashMap<>();
keySubgraphMap.put( subgraph.getClassType(), subgraph );
}
else {
final SubGraphImplementor<T> existing = getKeySubgraph( subgraph.getClassType() );
if ( existing == null ) {
keySubgraphMap.put( subgraph.getClassType(), subgraph );
}
else {
existing.merge( subgraph );
}
//noinspection unchecked
return (SubGraphImplementor<T>) keySubgraph;
}
}
@Override
public SubGraphImplementor<?> makeKeySubGraph() {
return makeKeySubGraph( (ManagedDomainType<?>) attribute.getKeyGraphType() );
verifyMutability();
return keySubgraph( (ManagedDomainType<?>) attribute.getKeyGraphType() );
}
@Override
public <S> SubGraphImplementor<S> makeKeySubGraph(Class<S> type) {
return makeKeySubGraph( attribute.getDeclaringType().getMetamodel().managedType( type ) );
public <S> SubGraphImplementor<S> makeKeySubGraph(Class<S> 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<? super S> keyType = (ManagedDomainType<? super S>) type;
final SubGraphImplementor<? super S> keySubgraph = keySubgraph( keyType );
if ( type.getBindableJavaType() == subtype ) {
//noinspection unchecked
return (SubGraphImplementor<S>) keySubgraph;
}
else {
return keySubgraph.addTreatedSubGraph( subtype );
}
}
@Override
public <S> SubGraphImplementor<S> makeKeySubGraph(ManagedDomainType<S> subtype) {
verifyMutability();
assert subtype != null;
final Class<S> javaType = subtype.getJavaType();
if ( !attribute.getKeyGraphType().getBindableJavaType().isAssignableFrom( javaType ) ) {
final DomainType<?> type = attribute.getKeyGraphType();
final Class<S> javaType = subtype.getBindableJavaType();
if ( !type.getBindableJavaType().isAssignableFrom( javaType ) ) {
throw new IllegalArgumentException( "Not a key subtype: " + javaType.getName() );
}
final SubGraphImplementor<S> existing = keySubgraphMap == null ? null : getKeySubgraph( javaType );
if ( existing != null ) {
return existing;
@SuppressWarnings("unchecked")
final ManagedDomainType<? super S> keyType = (ManagedDomainType<? super S>) type;
final SubGraphImplementor<? super S> keySubgraph = keySubgraph( keyType );
if ( type.getBindableJavaType() == javaType ) {
//noinspection unchecked
return (SubGraphImplementor<S>) keySubgraph;
}
else {
final SubGraphImplementor<S> subgraph = new SubGraphImpl<>( subtype, true );
addKeySubGraph( subgraph );
return subgraph;
return keySubgraph.addTreatedSubGraph( subtype );
}
}
@Override
public AttributeNodeImplementor<J> 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 <U,V> Map<Class<? extends U>, SubGraphImplementor<? extends V>> makeMapCopy(
boolean mutable,
Map<Class<? extends U>, SubGraphImplementor<? extends V>> nodeMap) {
if ( nodeMap == null ) {
return null;
@Override
public void merge(AttributeNodeImplementor<J> other, boolean mutable) {
final SubGraphImplementor<?> otherSubgraph = other.getSubGraph();
if ( otherSubgraph != null ) {
if ( subgraph == null ) {
subgraph = otherSubgraph.makeCopy( mutable );
}
else {
final HashMap<Class<? extends U>, SubGraphImplementor<? extends V>> map = new HashMap<>( nodeMap.size() );
nodeMap.forEach( (attribute, subgraph) -> map.put( attribute, subgraph.makeCopy( mutable ) ) );
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<Class<?>, SubGraphImplementor<?>> getSubGraphMap() {
if ( subgraph == null ) {
return emptyMap();
}
else {
final HashMap<Class<?>, SubGraphImplementor<?>> map = new HashMap<>( subgraph.getSubGraphMap() );
map.put( attribute.getValueGraphType().getBindableJavaType(), subgraph );
return map;
}
}
@Override
public void merge(AttributeNodeImplementor<J> other) {
other.getSubGraphMap().values().forEach( this::mergeToSubgraph );
other.getKeySubGraphMap().values().forEach( this::mergeToKeySubgraph );
}
private <T> void mergeToKeySubgraph(SubGraphImplementor<T> subgraph) {
final SubGraphImplementor<T> existing = getKeySubgraphForPut( subgraph );
if ( existing != null ) {
existing.merge( subgraph );
public Map<Class<?>, SubGraphImplementor<?>> getKeySubGraphMap() {
if ( keySubgraph == null ) {
return emptyMap();
}
else {
addKeySubGraph( subgraph.makeCopy( true ) );
final HashMap<Class<?>, SubGraphImplementor<?>> map = new HashMap<>( keySubgraph.getSubGraphMap() );
map.put( attribute.getKeyGraphType().getJavaType(), keySubgraph );
return map;
}
}
private <T> void mergeToSubgraph(SubGraphImplementor<T> subgraph) {
final SubGraphImplementor<T> existing = getSubgraphForPut( subgraph );
if ( existing != null ) {
existing.merge( subgraph );
@Override
public @SuppressWarnings("rawtypes") Map<Class, Subgraph> getSubgraphs() {
if ( subgraph == null ) {
return emptyMap();
}
else {
addSubGraph( subgraph.makeCopy( true ) );
final HashMap<Class, Subgraph> map = new HashMap<>( subgraph.getSubGraphMap() );
map.put( attribute.getValueGraphType().getBindableJavaType(), subgraph );
return map;
}
}
private <T> SubGraphImplementor<T> getSubgraphForPut(SubGraphImplementor<T> subgraph) {
if ( subgraphMap == null ) {
subgraphMap = new HashMap<>();
return null;
@Override
public @SuppressWarnings("rawtypes") Map<Class, Subgraph> getKeySubgraphs() {
if ( keySubgraph == null ) {
return emptyMap();
}
else {
return getSubgraph( subgraph.getClassType() );
final HashMap<Class, Subgraph> map = new HashMap<>( keySubgraph.getSubGraphMap() );
map.put( attribute.getKeyGraphType().getJavaType(), keySubgraph );
return map;
}
}
private <T> SubGraphImplementor<T> getKeySubgraphForPut(SubGraphImplementor<T> subgraph) {
if ( keySubgraphMap == null ) {
keySubgraphMap = new HashMap<>();
return null;
}
else {
return getKeySubgraph( subgraph.getClassType() );
}
}
@SuppressWarnings("unchecked")
private <T> SubGraphImplementor<T> getSubgraph(Class<T> incomingSubtype) {
return (SubGraphImplementor<T>) subgraphMap.get( incomingSubtype );
}
@SuppressWarnings("unchecked")
private <T> SubGraphImplementor<T> getKeySubgraph(Class<T> incomingSubtype) {
return (SubGraphImplementor<T>) keySubgraphMap.get( incomingSubtype );
}
}

View File

@ -22,10 +22,6 @@ public class SubGraphImpl<J> extends AbstractGraph<J> implements SubGraphImpleme
super( original, mutable );
}
public SubGraphImpl(ManagedDomainType<J> managedDomainType, AbstractGraph<? super J> original, boolean mutable) {
super( managedDomainType, original, mutable );
}
@Override
public SubGraphImplementor<J> makeCopy(boolean mutable) {
return new SubGraphImpl<>( this, mutable );

View File

@ -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<J> extends AttributeNode<J>, GraphNodeImplementor<J> {
Map<Class<?>, SubGraphImplementor<?>> getSubGraphMap();
Map<Class<?>, SubGraphImplementor<?>> getKeySubGraphMap();
@Override
default Map<Class<?>, ? extends SubGraph<?>> getSubGraphs() {
return unmodifiableMap( getSubGraphMap() );
}
@Override
default Map<Class<?>, ? extends SubGraph<?>> getKeySubGraphs() {
return unmodifiableMap( getKeySubGraphMap() );
}
@Override // JPA API uses raw types
default @SuppressWarnings("rawtypes") Map<Class, Subgraph> getSubgraphs() {
return unmodifiableMap( getSubGraphMap() );
}
@Override // JPA API uses raw types
default @SuppressWarnings("rawtypes") Map<Class, Subgraph> getKeySubgraphs() {
return unmodifiableMap( getKeySubGraphMap() );
}
@Override
AttributeNodeImplementor<J> makeCopy(boolean mutable);
@ -55,10 +28,10 @@ public interface AttributeNodeImplementor<J> extends AttributeNode<J>, GraphNode
SubGraphImplementor<?> makeKeySubGraph();
@Override
<S> SubGraphImplementor<S> makeSubGraph(Class<S> type);
<S> SubGraphImplementor<S> makeSubGraph(Class<S> subtype);
@Override
<S> SubGraphImplementor<S> makeKeySubGraph(Class<S> type);
<S> SubGraphImplementor<S> makeKeySubGraph(Class<S> subtype);
@Override
<S> SubGraphImplementor<S> makeSubGraph(ManagedDomainType<S> subtype);
@ -66,9 +39,23 @@ public interface AttributeNodeImplementor<J> extends AttributeNode<J>, GraphNode
@Override
<S> SubGraphImplementor<S> makeKeySubGraph(ManagedDomainType<S> subtype);
void merge(AttributeNodeImplementor<J> other);
void merge(AttributeNodeImplementor<J> other, boolean mutable);
void addSubGraph(SubGraphImplementor<?> subgraph);
SubGraphImplementor<?> getSubGraph();
void addKeySubGraph(SubGraphImplementor<?> subgraph);
SubGraphImplementor<?> getKeySubGraph();
Map<Class<?>, SubGraphImplementor<?>> getSubGraphMap();
Map<Class<?>, SubGraphImplementor<?>> getKeySubGraphMap();
@Override
default Map<Class<?>, ? extends SubGraph<?>> getSubGraphs() {
return getSubGraphMap();
}
@Override
default Map<Class<?>, ? extends SubGraph<?>> getKeySubGraphs() {
return getKeySubGraphMap();
}
}

View File

@ -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<J> extends Graph<J>, GraphNodeImplementor<J> {
void merge(GraphImplementor<J> other);
void merge(GraphImplementor<? super J> other);
void merge(GraphImplementor<? super J> other, boolean mutable);
@Override @Deprecated(forRemoval = true)
RootGraphImplementor<J> makeRootGraph(String name, boolean mutable)
@ -72,11 +75,19 @@ public interface GraphImplementor<J> extends Graph<J>, GraphNodeImplementor<J> {
<AJ> SubGraphImplementor<AJ> addKeySubGraph(String attributeName, Class<AJ> subtype);
@Override
<AJ> SubGraphImplementor<AJ> addSubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> subtype);
<AJ> SubGraphImplementor<AJ> addSubGraph(PersistentAttribute<? super J, ? super AJ> attribute, ManagedDomainType<AJ> subtype);
<AJ> SubGraphImplementor<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, Class<AJ> type);
<AJ> SubGraphImplementor<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, ManagedDomainType<AJ> type);
@Override
<AJ> SubGraphImplementor<AJ> addKeySubGraph(PersistentAttribute<? super J, ? super AJ> attribute, ManagedDomainType<AJ> subtype);
<AJ> SubGraphImplementor<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> subtype);
@Override
<Y extends J> SubGraphImplementor<Y> addTreatedSubGraph(Class<Y> type);
<Y extends J> SubGraphImplementor<Y> addTreatedSubGraph(ManagedDomainType<Y> type);
Map<Class<?>, SubGraphImplementor<?>> getSubGraphMap();
}

View File

@ -25,7 +25,7 @@ public class EntityGraphsTest extends AbstractEntityGraphTest {
}
@SafeVarargs
private final void checkMerge(EntityGraph<GraphParsingTestEntity> expected, EntityGraph<GraphParsingTestEntity>... graphs) {
private void checkMerge(EntityGraph<GraphParsingTestEntity> expected, EntityGraph<GraphParsingTestEntity>... graphs) {
checkMerge( GraphParsingTestEntity.class, expected, graphs );
}