Skip to content

Commit 3236d46

Browse files
committed
Graphpocalypse: major revision/refactoring of EntityGraph support
- add Javadoc, which has been missing for many years - add a missing operation
1 parent 0e02369 commit 3236d46

File tree

5 files changed

+215
-32
lines changed

5 files changed

+215
-32
lines changed

hibernate-core/src/main/java/org/hibernate/graph/AttributeNode.java

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,53 @@
1414
import static java.util.Collections.unmodifiableMap;
1515

1616
/**
17-
* Extends the JPA-defined {@link AttributeNode} with additional operations.
17+
* Represents a fetched {@linkplain jakarta.persistence.metamodel.Attribute attribute} in an
18+
* {@linkplain Graph entity graph}.
19+
* <p>
20+
* An {@code AttributeNode} representing an attribute whose type is a managed type or collection
21+
* of some managed type may have an associated <em>value subgraph</em>, which is represented by
22+
* an instance of {@link SubGraph}.
23+
* <ul>
24+
* <li>For a {@linkplain jakarta.persistence.metamodel.SingularAttribute singular attribute},
25+
* the value type is the type of the attribute.
26+
* <li>For a {@linkplain jakarta.persistence.metamodel.PluralAttribute plural attribute}, the
27+
* value type is the collection element type.
28+
* </ul>
29+
* <p>
30+
* Or, if the represented attribute is a {@link Map}, the {@code AttributeNode} maye have an
31+
* associated <em>key subgraph</em>, similarly represented by a {@link SubGraph}.
32+
* <p>
33+
* Not every attribute node has a subgraph.
34+
* <p>
35+
* Extends the JPA-defined {@link jakarta.persistence.AttributeNode} with additional operations.
36+
*
37+
* @apiNote Historically, this interface declared operations with incorrect generic types,
38+
* leading to unsound code. This was in Hibernate 7, with possible breakage to older code.
1839
*
1940
* @author Strong Liu
2041
* @author Steve Ebersole
2142
* @author Andrea Boriero
43+
* @author Gavin King
2244
*/
2345
public interface AttributeNode<J> extends GraphNode<J>, jakarta.persistence.AttributeNode<J> {
2446

47+
/**
48+
* The {@link PersistentAttribute} represented by this node.
49+
*/
2550
PersistentAttribute<?, J> getAttributeDescriptor();
2651

52+
/**
53+
* All value subgraphs rooted at this node.
54+
*
55+
* @see jakarta.persistence.AttributeNode#getSubgraphs
56+
*/
2757
Map<Class<?>, ? extends SubGraph<?>> getSubGraphs();
58+
59+
/**
60+
* All key subgraphs rooted at this node.
61+
*
62+
* @see jakarta.persistence.AttributeNode#getKeySubgraphs
63+
*/
2864
Map<Class<?>, ? extends SubGraph<?>> getKeySubGraphs();
2965

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

76+
/**
77+
* Create and return a new value {@link SubGraph} rooted at this node,
78+
* or return an existing such {@link SubGraph} if there is one.
79+
*/
4080
SubGraph<?> makeSubGraph();
81+
82+
/**
83+
* Create and return a new key {@link SubGraph} rooted at this node,
84+
* or return an existing such {@link SubGraph} if there is one.
85+
*/
4186
SubGraph<?> makeKeySubGraph();
4287

88+
/**
89+
* Create and return a new value {@link SubGraph} rooted at this node,
90+
* with the given type, which may be a subtype of the value type,
91+
* or return an existing such {@link SubGraph} if there is one.
92+
*/
4393
<S> SubGraph<S> makeSubGraph(Class<S> subtype);
94+
95+
/**
96+
* Create and return a new value {@link SubGraph} rooted at this node,
97+
* with the given type, which may be a subtype of the key type,
98+
* or return an existing such {@link SubGraph} if there is one.
99+
*/
44100
<S> SubGraph<S> makeKeySubGraph(Class<S> subtype);
45101

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

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

hibernate-core/src/main/java/org/hibernate/graph/Graph.java

Lines changed: 130 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,40 @@
77
import java.util.List;
88

99
import jakarta.persistence.metamodel.Attribute;
10+
import jakarta.persistence.metamodel.MapAttribute;
1011
import jakarta.persistence.metamodel.PluralAttribute;
1112
import org.hibernate.metamodel.model.domain.ManagedDomainType;
1213
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
1314
import org.hibernate.metamodel.model.domain.PersistentAttribute;
1415
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
1516

1617
/**
17-
* A container for {@link AttributeNode} references.
18+
* Represents a {@link jakarta.persistence.metamodel.ManagedType managed type} in an
19+
* {@linkplain Graph entity graph}, acting as a container for:
20+
* <ul>
21+
* <li>{@link AttributeNode} references representing fetched attributes, and
22+
* <li><em>treated subgraphs</em>, each represented by a child instance of
23+
* {@link SubGraph}.
24+
* </ul>
25+
* <p>
26+
* A treated (narrowed) subgraph allows fetching to be specified for any attribute of
27+
* any subtype of the type represented by this graph. The usual way to create a treated
28+
* subgraph is by calling {@link jakarta.persistence.EntityGraph#addTreatedSubgraph(Class)}
29+
* or {@link #addTreatedSubGraph(Class)}. There are various shortcut operations such as
30+
* {@link jakarta.persistence.EntityGraph#addTreatedSubgraph(Attribute, Class)} and
31+
* {@link #addSubGraph(PersistentAttribute, Class)} which combine creation of a subgraph
32+
* with creation of a treated subgraph.
33+
* <p>
34+
* Extends the JPA-defined {@link jakarta.persistence.Graph} with additional operations.
1835
*
19-
* @apiNote Acts as an abstraction over the JPA-defined interfaces
20-
* {@link jakarta.persistence.EntityGraph} and
21-
* {@link jakarta.persistence.Subgraph}, which have no
22-
* common supertype.
36+
* @apiNote Historically, both {@link jakarta.persistence.EntityGraph} and this interface
37+
* declared operations with incorrect generic types, leading to unsound code. This was
38+
* rectified in JPA 3.2 and Hibernate 7, with possible breakage to older code.
2339
*
2440
* @author Strong Liu
2541
* @author Steve Ebersole
2642
* @author Andrea Boriero
43+
* @author Gavin King
2744
*
2845
* @see RootGraph
2946
* @see SubGraph
@@ -33,23 +50,17 @@
3350
public interface Graph<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {
3451

3552
/**
36-
* Get a list of all existing AttributeNodes within this container.
37-
*
38-
* @see #getAttributeNodes
39-
*/
40-
List<? extends AttributeNode<?>> getAttributeNodeList();
41-
42-
/**
43-
* Graphs apply only to {@link jakarta.persistence.metamodel.ManagedType}s.
53+
* The {@linkplain jakarta.persistence.metamodel.ManagedType managed type}
54+
* of the node.
4455
*
4556
* @return the {@code ManagedType} being graphed here.
4657
*/
4758
ManagedDomainType<J> getGraphedType();
4859

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

6273
/**
63-
* Create a new (mutable or immutable) {@link SubGraph} rooted at
64-
* this {@link Graph}.
74+
* Create a new {@linkplain SubGraph subgraph} representing this node.
6575
*
6676
* @deprecated This will be removed
6777
*/
6878
@Deprecated(since = "7.0", forRemoval = true)
6979
SubGraph<J> makeSubGraph(boolean mutable);
7080

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

7490

7591
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76-
// AttributeNode handling
92+
// AttributeNodes
93+
94+
/**
95+
* All {@linkplain AttributeNode nodes} belonging to this container.
96+
*
97+
* @see #getAttributeNodes
98+
*/
99+
List<? extends AttributeNode<?>> getAttributeNodeList();
77100

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

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

127150

128151
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
129-
// Subgraph nodes
152+
// Subgraphs
130153

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

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

135170
/**
136171
* Create and return a new (mutable) {@link SubGraph} associated with
137-
* the named {@link AttributeNode}.
172+
* the named {@link Attribute}, or return an existing such {@link SubGraph}
173+
* if there is one.
138174
*
139-
* @apiNote If no such AttributeNode exists yet, it is created.
175+
* @see #addSubgraph(String)
140176
*/
141177
@Deprecated
142178
<AJ> SubGraph<AJ> addSubGraph(String attributeName)
143179
throws CannotContainSubGraphException;
144180

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

148192
/**
149193
* Create and return a new (mutable) {@link SubGraph} associated with
150-
* the {@link AttributeNode} for the given attribute.
194+
* the given {@link PersistentAttribute}, or return an existing such
195+
* {@link SubGraph} if there is one.
151196
*
152-
* @apiNote If no such AttributeNode exists yet, it is created.
197+
* @see #addSubgraph(Attribute)
153198
*/
154199
<AJ> SubGraph<AJ> addSubGraph(PersistentAttribute<? super J, AJ> attribute)
155200
throws CannotContainSubGraphException;
156201

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

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

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

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

242+
/**
243+
* Create and return a new (mutable) {@link SubGraph} associated with
244+
* the key of the named map or return an existing such {@link SubGraph}
245+
* if there is one.
246+
*
247+
* @see #addKeySubgraph(String)
248+
*/
169249
@Deprecated
170250
<AJ> SubGraph<AJ> addKeySubGraph(String attributeName)
171251
throws CannotContainSubGraphException;
172252

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

264+
/**
265+
* Create and return a new (mutable) {@link SubGraph} associated with
266+
* the key of the named map, and with the given type, which may be a
267+
* subtype of the attribute type, or return an existing such
268+
* {@link SubGraph} if there is one.
269+
*
270+
* @see #addTreatedMapKeySubgraph(MapAttribute, Class)
271+
*/
272+
<AJ> SubGraph<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, Class<AJ> type)
273+
throws CannotContainSubGraphException;
274+
275+
/**
276+
* Create and return a new (mutable) {@link SubGraph} associated with
277+
* the key of the named map, and with the given type, which may be a
278+
* subtype of the attribute type, or return an existing such
279+
* {@link SubGraph} if there is one.
280+
*/
176281
<AJ> SubGraph<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> type)
177282
throws CannotContainSubGraphException;
178283

hibernate-core/src/main/java/org/hibernate/graph/internal/AbstractGraph.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
* Base class for {@link RootGraph} and {@link SubGraph} implementations.
3939
*
4040
* @author Steve Ebersole
41+
* @author Gavin King
4142
*/
4243
public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements GraphImplementor<J> {
4344

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

323+
@Override
324+
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, Class<AJ> subtype) {
325+
return findOrCreateAttributeNode( attribute ).makeKeySubGraph( subtype );
326+
}
327+
322328
@Override
323329
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(MapPersistentAttribute<? super J, ? super AJ, ?> attribute, ManagedDomainType<AJ> subtype) {
324330
return findOrCreateAttributeNode( attribute ).makeKeySubGraph( subtype );

hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* Implementation of {@link jakarta.persistence.AttributeNode}.
2323
*
2424
* @author Steve Ebersole
25+
* @author Gavin King
2526
*/
2627
public class AttributeNodeImpl<J,V,K>
2728
extends AbstractGraphNode<J>

0 commit comments

Comments
 (0)