Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,53 @@
import static java.util.Collections.unmodifiableMap;

/**
* Extends the JPA-defined {@link AttributeNode} with additional operations.
* Represents a fetched {@linkplain jakarta.persistence.metamodel.Attribute attribute} in an
* {@linkplain Graph entity graph}.
* <p>
* An {@code AttributeNode} representing an attribute whose type is a managed type or collection
* of some managed type may have an associated <em>value subgraph</em>, which is represented by
* an instance of {@link SubGraph}.
* <ul>
* <li>For a {@linkplain jakarta.persistence.metamodel.SingularAttribute singular attribute},
* the value type is the type of the attribute.
* <li>For a {@linkplain jakarta.persistence.metamodel.PluralAttribute plural attribute}, the
* value type is the collection element type.
* </ul>
* <p>
* Or, if the represented attribute is a {@link Map}, the {@code AttributeNode} maye have an
* associated <em>key subgraph</em>, similarly represented by a {@link SubGraph}.
* <p>
* Not every attribute node has a subgraph.
* <p>
* Extends the JPA-defined {@link jakarta.persistence.AttributeNode} with additional operations.
*
* @apiNote Historically, this interface declared operations with incorrect generic types,
* leading to unsound code. This was in Hibernate 7, with possible breakage to older code.
*
* @author Strong Liu
* @author Steve Ebersole
* @author Andrea Boriero
* @author Gavin King
*/
public interface AttributeNode<J> extends GraphNode<J>, jakarta.persistence.AttributeNode<J> {

/**
* The {@link PersistentAttribute} represented by this node.
*/
PersistentAttribute<?, J> getAttributeDescriptor();

/**
* All value subgraphs rooted at this node.
*
* @see jakarta.persistence.AttributeNode#getSubgraphs
*/
Map<Class<?>, ? extends SubGraph<?>> getSubGraphs();

/**
* All key subgraphs rooted at this node.
*
* @see jakarta.persistence.AttributeNode#getKeySubgraphs
*/
Map<Class<?>, ? extends SubGraph<?>> getKeySubGraphs();

@Override
Expand All @@ -37,13 +73,43 @@ public interface AttributeNode<J> extends GraphNode<J>, jakarta.persistence.Attr
return unmodifiableMap( getKeySubGraphs() );
}

/**
* Create and return a new value {@link SubGraph} rooted at this node,
* or return an existing such {@link SubGraph} if there is one.
*/
SubGraph<?> makeSubGraph();

/**
* Create and return a new key {@link SubGraph} rooted at this node,
* or return an existing such {@link SubGraph} if there is one.
*/
SubGraph<?> makeKeySubGraph();

/**
* Create and return a new value {@link SubGraph} rooted at this node,
* with the given type, which may be a subtype of the value type,
* or return an existing such {@link SubGraph} if there is one.
*/
<S> SubGraph<S> makeSubGraph(Class<S> subtype);

/**
* Create and return a new value {@link SubGraph} rooted at this node,
* with the given type, which may be a subtype of the key type,
* or return an existing such {@link SubGraph} if there is one.
*/
<S> SubGraph<S> makeKeySubGraph(Class<S> subtype);

/**
* Create and return a new value {@link SubGraph} rooted at this node,
* with the given type, which may be a subtype of the value type,
* or return an existing such {@link SubGraph} if there is one.
*/
<S> SubGraph<S> makeSubGraph(ManagedDomainType<S> subtype);
<S> SubGraph<S> makeKeySubGraph(ManagedDomainType<S> subtype);

/**
* Create and return a new value {@link SubGraph} rooted at this node,
* with the given type, which may be a subtype of the key type,
* or return an existing such {@link SubGraph} if there is one.
*/
<S> SubGraph<S> makeKeySubGraph(ManagedDomainType<S> subtype);
}
155 changes: 130 additions & 25 deletions hibernate-core/src/main/java/org/hibernate/graph/Graph.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,40 @@
import java.util.List;

import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.MapAttribute;
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.
* Represents a {@link jakarta.persistence.metamodel.ManagedType managed type} in an
* {@linkplain Graph entity graph}, acting as a container for:
* <ul>
* <li>{@link AttributeNode} references representing fetched attributes, and
* <li><em>treated subgraphs</em>, each represented by a child instance of
* {@link SubGraph}.
* </ul>
* <p>
* A treated (narrowed) subgraph allows fetching to be specified for any attribute of
* any subtype of the type represented by this graph. The usual way to create a treated
* subgraph is by calling {@link jakarta.persistence.EntityGraph#addTreatedSubgraph(Class)}
* or {@link #addTreatedSubGraph(Class)}. There are various shortcut operations such as
* {@link jakarta.persistence.EntityGraph#addTreatedSubgraph(Attribute, Class)} and
* {@link #addSubGraph(PersistentAttribute, Class)} which combine creation of a subgraph
* with creation of a treated subgraph.
* <p>
* Extends the JPA-defined {@link jakarta.persistence.Graph} with additional operations.
*
* @apiNote Acts as an abstraction over the JPA-defined interfaces
* {@link jakarta.persistence.EntityGraph} and
* {@link jakarta.persistence.Subgraph}, which have no
* common supertype.
* @apiNote Historically, both {@link jakarta.persistence.EntityGraph} and this interface
* declared operations with incorrect generic types, leading to unsound code. This was
* rectified in JPA 3.2 and Hibernate 7, with possible breakage to older code.
*
* @author Strong Liu
* @author Steve Ebersole
* @author Andrea Boriero
* @author Gavin King
*
* @see RootGraph
* @see SubGraph
Expand All @@ -33,23 +50,17 @@
public interface Graph<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {

/**
* Get a list of all existing AttributeNodes within this container.
*
* @see #getAttributeNodes
*/
List<? extends AttributeNode<?>> getAttributeNodeList();

/**
* Graphs apply only to {@link jakarta.persistence.metamodel.ManagedType}s.
* The {@linkplain jakarta.persistence.metamodel.ManagedType managed type}
* of the node.
*
* @return the {@code ManagedType} being graphed here.
*/
ManagedDomainType<J> getGraphedType();

/**
* Create a named root {@link Graph} if the given name is not null.
* Create a named {@linkplain RootGraph root graph} representing this node.
*
* @param mutable controls whether the resulting {@code Graph} is mutable
* @param mutable controls whether the resulting graph is mutable
*
* @throws CannotBecomeEntityGraphException If the named attribute is not entity-valued
*
Expand All @@ -60,20 +71,32 @@ RootGraph<J> makeRootGraph(String name, boolean mutable)
throws CannotBecomeEntityGraphException;

/**
* Create a new (mutable or immutable) {@link SubGraph} rooted at
* this {@link Graph}.
* Create a new {@linkplain SubGraph subgraph} representing this node.
*
* @deprecated This will be removed
*/
@Deprecated(since = "7.0", forRemoval = true)
SubGraph<J> makeSubGraph(boolean mutable);

/**
* Make a copy of this graph node, with the given mutability.
* <p>
* If this graph is immutable, and the argument is {@code false},
* simply return this instance.
*/
@Override
Graph<J> makeCopy(boolean mutable);


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AttributeNode handling
// AttributeNodes

/**
* All {@linkplain AttributeNode nodes} belonging to this container.
*
* @see #getAttributeNodes
*/
List<? extends AttributeNode<?>> getAttributeNodeList();

/**
* Find an already existing AttributeNode by attributeName within
Expand Down Expand Up @@ -112,8 +135,8 @@ default boolean hasAttributeNode(Attribute<? super J, ?> attribute) {
}

/**
* Add an {@link AttributeNode} (with no associated {@link SubGraph})
* to this container by attribute reference.
* Add an {@link AttributeNode} representing the given {@link PersistentAttribute}
* to this node of the graph without creating any associated {@link SubGraph}.
*
* @see #addAttributeNode(Attribute)
*/
Expand All @@ -126,53 +149,135 @@ default <Y> AttributeNode<Y> addAttributeNode(Attribute<? super J, Y> attribute)


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Subgraph nodes
// Subgraphs

/**
* Create and return a new (mutable) {@link SubGraph} representing
* the given subtype of the type of this node, or return an existing
* such {@link SubGraph} if there is one.
*
* @see jakarta.persistence.EntityGraph#addTreatedSubgraph(Class)
*/
<Y extends J> SubGraph<Y> addTreatedSubGraph(Class<Y> type);

/**
* Create and return a new (mutable) {@link SubGraph} representing
* the given subtype of the type of this node, or return an existing
* such {@link SubGraph} if there is one.
*/
<Y extends J> SubGraph<Y> addTreatedSubGraph(ManagedDomainType<Y> type);

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the named {@link AttributeNode}.
* the named {@link Attribute}, or return an existing such {@link SubGraph}
* if there is one.
*
* @apiNote If no such AttributeNode exists yet, it is created.
* @see #addSubgraph(String)
*/
@Deprecated
<AJ> SubGraph<AJ> addSubGraph(String attributeName)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the named {@link Attribute}, and with the given type, which may be
* a subtype of the attribute type, or return an existing such
* {@link SubGraph} if there is one.
*
* @see #addSubgraph(String, Class)
*/
<AJ> SubGraph<AJ> addSubGraph(String attributeName, Class<AJ> type)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the {@link AttributeNode} for the given attribute.
* the given {@link PersistentAttribute}, or return an existing such
* {@link SubGraph} if there is one.
*
* @apiNote If no such AttributeNode exists yet, it is created.
* @see #addSubgraph(Attribute)
*/
<AJ> SubGraph<AJ> addSubGraph(PersistentAttribute<? super J, AJ> attribute)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the given {@link PersistentAttribute}, and with the given type,
* which may be a subtype of the attribute type, or return an existing
* such {@link SubGraph} if there is one.
*
* @see #addSubgraph(Attribute, Class)
*/
<AJ> SubGraph<AJ> addSubGraph(PersistentAttribute<? super J, ? super AJ> attribute, Class<AJ> type)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the given {@link PersistentAttribute}, and with the given type,
* which may be a subtype of the attribute type, or return an existing
* such {@link SubGraph} if there is one.
*/
<AJ> SubGraph<AJ> addSubGraph(PersistentAttribute<? super J, ? super AJ> attribute, ManagedDomainType<AJ> type)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the element of the given collection, and with the given type, which
* may be a subtype of the attribute type, or return an existing such
* {@link SubGraph} if there is one.
*
* @see #addTreatedElementSubgraph(PluralAttribute, Class)
*/
<AJ> SubGraph<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, Class<AJ> type)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the element of the given collection, and with the given type, which
* may be a subtype of the attribute type, or return an existing such
* {@link SubGraph} if there is one.
*/
<AJ> SubGraph<AJ> addElementSubGraph(PluralPersistentAttribute<? super J, ?, ? super AJ> attribute, ManagedDomainType<AJ> type)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the key of the named map or return an existing such {@link SubGraph}
* if there is one.
*
* @see #addKeySubgraph(String)
*/
@Deprecated
<AJ> SubGraph<AJ> addKeySubGraph(String attributeName)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the key of the named map, and with the given type, which may be a
* subtype of the attribute type, or return an existing such
* {@link SubGraph} if there is one.
*
* @see #addKeySubgraph(String, Class)
*/
<AJ> SubGraph<AJ> addKeySubGraph(String attributeName, Class<AJ> type)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the key of the named map, and with the given type, which may be a
* subtype of the attribute type, or return an existing such
* {@link SubGraph} if there is one.
*
* @see #addTreatedMapKeySubgraph(MapAttribute, Class)
*/
<AJ> SubGraph<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, Class<AJ> type)
throws CannotContainSubGraphException;

/**
* Create and return a new (mutable) {@link SubGraph} associated with
* the key of the named map, and with the given type, which may be a
* subtype of the attribute type, or return an existing such
* {@link SubGraph} if there is one.
*/
<AJ> SubGraph<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> type)
throws CannotContainSubGraphException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
* Base class for {@link RootGraph} and {@link SubGraph} implementations.
*
* @author Steve Ebersole
* @author Gavin King
*/
public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements GraphImplementor<J> {

Expand Down Expand Up @@ -319,6 +320,11 @@ public <AJ> SubGraphImplementor<AJ> addElementSubGraph(PluralPersistentAttribute
return findOrCreateAttributeNode( attribute ).makeSubGraph( type );
}

@Override
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, Class<AJ> subtype) {
return findOrCreateAttributeNode( attribute ).makeKeySubGraph( subtype );
}

@Override
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> subtype) {
return findOrCreateAttributeNode( attribute ).makeKeySubGraph( subtype );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* Implementation of {@link jakarta.persistence.AttributeNode}.
*
* @author Steve Ebersole
* @author Gavin King
*/
public class AttributeNodeImpl<J,V,K>
extends AbstractGraphNode<J>
Expand Down
Loading
Loading