Skip to content

Commit ebfdcdc

Browse files
committed
Graphpocalypse: modernize EntityGraphs utility class with new operations
1 parent 4e14127 commit ebfdcdc

File tree

2 files changed

+111
-29
lines changed

2 files changed

+111
-29
lines changed

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

+109-28
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,144 @@
44
*/
55
package org.hibernate.graph;
66

7+
import java.util.Arrays;
78
import java.util.List;
89
import java.util.Map;
910
import java.util.Set;
11+
import java.util.stream.Stream;
12+
1013
import jakarta.persistence.AttributeNode;
1114
import jakarta.persistence.EntityGraph;
1215
import jakarta.persistence.EntityManager;
16+
import jakarta.persistence.Graph;
1317
import jakarta.persistence.Query;
1418
import jakarta.persistence.Subgraph;
1519
import jakarta.persistence.TypedQuery;
1620

17-
import org.hibernate.Session;
1821
import org.hibernate.engine.spi.SessionImplementor;
1922
import org.hibernate.graph.spi.GraphImplementor;
2023
import org.hibernate.graph.spi.RootGraphImplementor;
24+
import org.hibernate.query.SelectionQuery;
2125

2226
/**
2327
* A collection of {@link EntityGraph} utilities.
2428
*
25-
* @apiNote These methods really belong inside other classes that we cannot modify.
29+
* @apiNote These operations are things which are arguably missing from JPA.
2630
*
2731
* @author asusnjar
32+
* @author Gavin King
2833
*/
2934
public final class EntityGraphs {
35+
3036
/**
3137
* Merges multiple entity graphs into a single graph that specifies the
3238
* fetching/loading of all attributes the input graphs specify.
3339
*
3440
* @param <T> Root entity type of the query and graph.
3541
*
36-
* @param entityManager EntityManager to use to create the new merged graph.
37-
* @param rootType Root type of the entity for which the graph is being merged.
42+
* @param entityManager {@code EntityManager} to use to create the new merged graph.
43+
* @param root Root type of the entity for which the graph is being merged.
3844
* @param graphs Graphs to merge.
3945
*
4046
* @return The merged graph.
4147
*/
4248
@SafeVarargs
43-
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> rootType, EntityGraph<T>... graphs) {
44-
return mergeInternal( (SessionImplementor) entityManager, rootType, graphs );
49+
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> root, Graph<T>... graphs) {
50+
return merge( entityManager, root, Arrays.stream(graphs) );
4551
}
4652

47-
@SafeVarargs
48-
public static <T> EntityGraph<T> merge(Session session, Class<T> rootType, Graph<T>... graphs) {
49-
return mergeInternal( (SessionImplementor) session, rootType, graphs );
53+
/**
54+
* Merges multiple entity graphs into a single graph that specifies the
55+
* fetching/loading of all attributes the input graphs specify.
56+
*
57+
* @param <T> Root entity type of the query and graph.
58+
*
59+
* @param entityManager {@code EntityManager} to use to create the new merged graph.
60+
* @param root Root type of the entity for which the graph is being merged.
61+
* @param graphs Graphs to merge.
62+
*
63+
* @return The merged graph.
64+
*
65+
* @since 7.0
66+
*/
67+
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> root, List<? extends Graph<T>> graphs) {
68+
return merge( entityManager, root, graphs.stream() );
5069
}
5170

52-
@SafeVarargs
53-
public static <T> EntityGraph<T> merge(SessionImplementor session, Class<T> rootType, GraphImplementor<T>... graphs) {
54-
return mergeInternal( session, rootType, graphs );
71+
/**
72+
* Merges multiple entity graphs into a single graph that specifies the
73+
* fetching/loading of all attributes the input graphs specify.
74+
*
75+
* @param <T> Root entity type of the query and graph.
76+
*
77+
* @param entityManager {@code EntityManager} to use to create the new merged graph.
78+
* @param root Root type of the entity for which the graph is being merged.
79+
* @param graphs Graphs to merge.
80+
*
81+
* @return The merged graph.
82+
*
83+
* @since 7.0
84+
*/
85+
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> root, Stream<? extends Graph<T>> graphs) {
86+
final RootGraphImplementor<T> merged = ((SessionImplementor) entityManager).createEntityGraph( root );
87+
graphs.forEach( graph -> merged.merge( (GraphImplementor<T>) graph ) );
88+
return merged;
5589
}
5690

57-
private static <T> EntityGraph<T> mergeInternal(
58-
SessionImplementor session, Class<T> rootType, jakarta.persistence.Graph<T>[] graphs) {
59-
final RootGraphImplementor<T> merged = session.createEntityGraph( rootType );
60-
if ( graphs != null ) {
61-
for ( jakarta.persistence.Graph<T> graph : graphs ) {
62-
merged.merge( (GraphImplementor<T>) graph );
63-
}
64-
}
65-
return merged;
91+
/**
92+
* Convenience method to apply the given graph to the given query
93+
* without the need for a cast when working with JPA API.
94+
*
95+
* @param query The JPA {@link TypedQuery}
96+
* @param graph The JPA {@link EntityGraph} to apply
97+
* @param semantic The semantic to use when applying the graph
98+
*
99+
* @see SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)
100+
*
101+
* @since 7.0
102+
*/
103+
public static <R> void setGraph(TypedQuery<R> query, EntityGraph<R> graph, GraphSemantic semantic) {
104+
((org.hibernate.query.Query<R>) query).setEntityGraph( graph, semantic );
105+
}
106+
107+
/**
108+
* Convenience method to apply the given load graph to the given
109+
* query without the need for a cast when working with JPA API.
110+
*
111+
* @param query The JPA {@link TypedQuery}
112+
* @param graph The JPA {@link EntityGraph} to apply
113+
*
114+
* @since 7.0
115+
*/
116+
public static <R> void setLoadGraph(TypedQuery<R> query, EntityGraph<R> graph) {
117+
setGraph( query, graph, GraphSemantic.LOAD );
118+
}
119+
120+
/**
121+
* Convenience method to apply the given fetch graph to the given
122+
* query without the need for a cast when working with JPA API.
123+
*
124+
* @param query The JPA {@link TypedQuery}
125+
* @param graph The JPA {@link EntityGraph} to apply
126+
*
127+
* @since 7.0
128+
*/
129+
public static <R> void setFetchGraph(TypedQuery<R> query, EntityGraph<R> graph) {
130+
setGraph( query, graph, GraphSemantic.FETCH );
131+
}
132+
133+
/**
134+
* Allows a treated subgraph to ve created for a {@link Subgraph}, since the
135+
* JPA-standard operation {@link EntityGraph#addTreatedSubgraph(Class)} is
136+
* declared by {@link EntityGraph}.
137+
*
138+
* @param graph any {@linkplain Graph root graph or subgraph}
139+
* @param subtype the treated (narrowed) type
140+
*
141+
* @since 7.0
142+
*/
143+
public <S> Subgraph<S> addTreatedSubgraph(Graph<? super S> graph, Class<S> subtype) {
144+
return ((org.hibernate.graph.Graph<? super S>) graph).addTreatedSubGraph( subtype );
66145
}
67146

68147
/**
@@ -73,7 +152,7 @@ private static <T> EntityGraph<T> mergeInternal(
73152
* @param graph The graph to apply
74153
* @param semantic The semantic to use when applying the graph
75154
*
76-
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
155+
* @deprecated Since it is not type safe and returns a raw type
77156
*/
78157
@Deprecated(since = "7.0")
79158
public static @SuppressWarnings("rawtypes") List executeList(Query query, EntityGraph<?> graph, GraphSemantic semantic) {
@@ -94,7 +173,7 @@ private static <T> EntityGraph<T> mergeInternal(
94173
* the graph applies to that entity's type. JPA does not necessarily
95174
* require that, but it is by far the most common usage.
96175
*
97-
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
176+
* @deprecated Use {@link #setGraph(TypedQuery, EntityGraph, GraphSemantic)} instead
98177
*/
99178
@Deprecated(since = "7.0")
100179
public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph, GraphSemantic semantic) {
@@ -114,7 +193,7 @@ public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph,
114193
*
115194
* @return The result list
116195
*
117-
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
196+
* @deprecated Since it is not type safe, returns a raw type, and accepts a string
118197
*/
119198
@Deprecated(since = "7.0")
120199
public static @SuppressWarnings("rawtypes") List executeList(Query query, EntityGraph<?> graph, String semanticJpaHintName) {
@@ -133,7 +212,7 @@ public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph,
133212
* the graph applies to that entity's type. JPA does not necessarily
134213
* require that, but it is by far the most common usage.
135214
*
136-
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
215+
* @deprecated Since it accepts a string instead of {@link GraphSemantic}
137216
*/
138217
@Deprecated(since = "7.0")
139218
public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph, String semanticJpaHintName) {
@@ -152,7 +231,7 @@ public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph,
152231
* This is simply knowledge from JPA EG discussions, nothing that
153232
* is specifically mentioned or discussed in the spec.
154233
*
155-
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
234+
* @deprecated Since it is not type safe and returns a raw type
156235
*/
157236
@Deprecated(since = "7.0")
158237
public static @SuppressWarnings("rawtypes") List executeList(Query query, EntityGraph<?> graph) {
@@ -170,7 +249,7 @@ public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph,
170249
* the graph applies to that entity's type. JPA does not necessarily
171250
* require that, but it is by far the most common usage.
172251
*
173-
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
252+
* @deprecated Use {@link #setFetchGraph(TypedQuery, EntityGraph)} instead
174253
*/
175254
@Deprecated(since = "7.0")
176255
public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph) {
@@ -276,7 +355,9 @@ public static boolean areEqual(
276355
* Compares two entity subgraphs and returns {@code true} if they are equal,
277356
* ignoring attribute order.
278357
*/
279-
public static boolean areEqual(@SuppressWarnings("rawtypes") Subgraph a, @SuppressWarnings("rawtypes") Subgraph b) {
358+
public static boolean areEqual(
359+
@SuppressWarnings("rawtypes") Subgraph a,
360+
@SuppressWarnings("rawtypes") Subgraph b) {
280361
if ( a == b ) {
281362
return true;
282363
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
* <p>
2525
* The {@link #parseInto} methods parse the graph string into a passed graph, which may be a subgraph
2626
* <p>
27-
* Multiple graphs made for the same entity type can be merged. See {@link EntityGraphs#merge(SessionImplementor, Class, GraphImplementor...)}.
27+
* Multiple graphs made for the same entity type can be merged.
28+
* See {@link EntityGraphs#merge(EntityManager, Class, jakarta.persistence.Graph...)}.
2829
*
2930
* @author asusnjar
3031
*/

0 commit comments

Comments
 (0)