mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-09 04:34:49 +00:00
Graphpocalypse: modernize EntityGraphs utility class with new operations
This commit is contained in:
parent
4e14127f65
commit
ebfdcdc87e
@ -4,67 +4,146 @@
|
||||
*/
|
||||
package org.hibernate.graph;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jakarta.persistence.AttributeNode;
|
||||
import jakarta.persistence.EntityGraph;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.Graph;
|
||||
import jakarta.persistence.Query;
|
||||
import jakarta.persistence.Subgraph;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.graph.spi.GraphImplementor;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.query.SelectionQuery;
|
||||
|
||||
/**
|
||||
* A collection of {@link EntityGraph} utilities.
|
||||
*
|
||||
* @apiNote These methods really belong inside other classes that we cannot modify.
|
||||
* @apiNote These operations are things which are arguably missing from JPA.
|
||||
*
|
||||
* @author asusnjar
|
||||
* @author Gavin King
|
||||
*/
|
||||
public final class EntityGraphs {
|
||||
|
||||
/**
|
||||
* Merges multiple entity graphs into a single graph that specifies the
|
||||
* fetching/loading of all attributes the input graphs specify.
|
||||
*
|
||||
* @param <T> Root entity type of the query and graph.
|
||||
*
|
||||
* @param entityManager EntityManager to use to create the new merged graph.
|
||||
* @param rootType Root type of the entity for which the graph is being merged.
|
||||
* @param entityManager {@code EntityManager} to use to create the new merged graph.
|
||||
* @param root Root type of the entity for which the graph is being merged.
|
||||
* @param graphs Graphs to merge.
|
||||
*
|
||||
* @return The merged graph.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> rootType, EntityGraph<T>... graphs) {
|
||||
return mergeInternal( (SessionImplementor) entityManager, rootType, graphs );
|
||||
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> root, Graph<T>... graphs) {
|
||||
return merge( entityManager, root, Arrays.stream(graphs) );
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <T> EntityGraph<T> merge(Session session, Class<T> rootType, Graph<T>... graphs) {
|
||||
return mergeInternal( (SessionImplementor) session, rootType, graphs );
|
||||
/**
|
||||
* Merges multiple entity graphs into a single graph that specifies the
|
||||
* fetching/loading of all attributes the input graphs specify.
|
||||
*
|
||||
* @param <T> Root entity type of the query and graph.
|
||||
*
|
||||
* @param entityManager {@code EntityManager} to use to create the new merged graph.
|
||||
* @param root Root type of the entity for which the graph is being merged.
|
||||
* @param graphs Graphs to merge.
|
||||
*
|
||||
* @return The merged graph.
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> root, List<? extends Graph<T>> graphs) {
|
||||
return merge( entityManager, root, graphs.stream() );
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <T> EntityGraph<T> merge(SessionImplementor session, Class<T> rootType, GraphImplementor<T>... graphs) {
|
||||
return mergeInternal( session, rootType, graphs );
|
||||
}
|
||||
|
||||
private static <T> EntityGraph<T> mergeInternal(
|
||||
SessionImplementor session, Class<T> rootType, jakarta.persistence.Graph<T>[] graphs) {
|
||||
final RootGraphImplementor<T> merged = session.createEntityGraph( rootType );
|
||||
if ( graphs != null ) {
|
||||
for ( jakarta.persistence.Graph<T> graph : graphs ) {
|
||||
merged.merge( (GraphImplementor<T>) graph );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Merges multiple entity graphs into a single graph that specifies the
|
||||
* fetching/loading of all attributes the input graphs specify.
|
||||
*
|
||||
* @param <T> Root entity type of the query and graph.
|
||||
*
|
||||
* @param entityManager {@code EntityManager} to use to create the new merged graph.
|
||||
* @param root Root type of the entity for which the graph is being merged.
|
||||
* @param graphs Graphs to merge.
|
||||
*
|
||||
* @return The merged graph.
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static <T> EntityGraph<T> merge(EntityManager entityManager, Class<T> root, Stream<? extends Graph<T>> graphs) {
|
||||
final RootGraphImplementor<T> merged = ((SessionImplementor) entityManager).createEntityGraph( root );
|
||||
graphs.forEach( graph -> merged.merge( (GraphImplementor<T>) graph ) );
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to apply the given graph to the given query
|
||||
* without the need for a cast when working with JPA API.
|
||||
*
|
||||
* @param query The JPA {@link TypedQuery}
|
||||
* @param graph The JPA {@link EntityGraph} to apply
|
||||
* @param semantic The semantic to use when applying the graph
|
||||
*
|
||||
* @see SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static <R> void setGraph(TypedQuery<R> query, EntityGraph<R> graph, GraphSemantic semantic) {
|
||||
((org.hibernate.query.Query<R>) query).setEntityGraph( graph, semantic );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to apply the given load graph to the given
|
||||
* query without the need for a cast when working with JPA API.
|
||||
*
|
||||
* @param query The JPA {@link TypedQuery}
|
||||
* @param graph The JPA {@link EntityGraph} to apply
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static <R> void setLoadGraph(TypedQuery<R> query, EntityGraph<R> graph) {
|
||||
setGraph( query, graph, GraphSemantic.LOAD );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to apply the given fetch graph to the given
|
||||
* query without the need for a cast when working with JPA API.
|
||||
*
|
||||
* @param query The JPA {@link TypedQuery}
|
||||
* @param graph The JPA {@link EntityGraph} to apply
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static <R> void setFetchGraph(TypedQuery<R> query, EntityGraph<R> graph) {
|
||||
setGraph( query, graph, GraphSemantic.FETCH );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a treated subgraph to ve created for a {@link Subgraph}, since the
|
||||
* JPA-standard operation {@link EntityGraph#addTreatedSubgraph(Class)} is
|
||||
* declared by {@link EntityGraph}.
|
||||
*
|
||||
* @param graph any {@linkplain Graph root graph or subgraph}
|
||||
* @param subtype the treated (narrowed) type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public <S> Subgraph<S> addTreatedSubgraph(Graph<? super S> graph, Class<S> subtype) {
|
||||
return ((org.hibernate.graph.Graph<? super S>) graph).addTreatedSubGraph( subtype );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for {@linkplain Query#getResultList() executing the query},
|
||||
* applying the given {@link EntityGraph} using the specified semantic
|
||||
@ -73,7 +152,7 @@ private static <T> EntityGraph<T> mergeInternal(
|
||||
* @param graph The graph to apply
|
||||
* @param semantic The semantic to use when applying the graph
|
||||
*
|
||||
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
|
||||
* @deprecated Since it is not type safe and returns a raw type
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
public static @SuppressWarnings("rawtypes") List executeList(Query query, EntityGraph<?> graph, GraphSemantic semantic) {
|
||||
@ -94,7 +173,7 @@ private static <T> EntityGraph<T> mergeInternal(
|
||||
* the graph applies to that entity's type. JPA does not necessarily
|
||||
* require that, but it is by far the most common usage.
|
||||
*
|
||||
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
|
||||
* @deprecated Use {@link #setGraph(TypedQuery, EntityGraph, GraphSemantic)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
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,
|
||||
*
|
||||
* @return The result list
|
||||
*
|
||||
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
|
||||
* @deprecated Since it is not type safe, returns a raw type, and accepts a string
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
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,
|
||||
* the graph applies to that entity's type. JPA does not necessarily
|
||||
* require that, but it is by far the most common usage.
|
||||
*
|
||||
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
|
||||
* @deprecated Since it accepts a string instead of {@link GraphSemantic}
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
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,
|
||||
* This is simply knowledge from JPA EG discussions, nothing that
|
||||
* is specifically mentioned or discussed in the spec.
|
||||
*
|
||||
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
|
||||
* @deprecated Since it is not type safe and returns a raw type
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
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,
|
||||
* the graph applies to that entity's type. JPA does not necessarily
|
||||
* require that, but it is by far the most common usage.
|
||||
*
|
||||
* @deprecated Use {@link org.hibernate.query.SelectionQuery#setEntityGraph(EntityGraph, GraphSemantic)}
|
||||
* @deprecated Use {@link #setFetchGraph(TypedQuery, EntityGraph)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
public static <R> List<R> executeList(TypedQuery<R> query, EntityGraph<R> graph) {
|
||||
@ -276,7 +355,9 @@ public static boolean areEqual(
|
||||
* Compares two entity subgraphs and returns {@code true} if they are equal,
|
||||
* ignoring attribute order.
|
||||
*/
|
||||
public static boolean areEqual(@SuppressWarnings("rawtypes") Subgraph a, @SuppressWarnings("rawtypes") Subgraph b) {
|
||||
public static boolean areEqual(
|
||||
@SuppressWarnings("rawtypes") Subgraph a,
|
||||
@SuppressWarnings("rawtypes") Subgraph b) {
|
||||
if ( a == b ) {
|
||||
return true;
|
||||
}
|
||||
|
@ -24,7 +24,8 @@
|
||||
* <p>
|
||||
* The {@link #parseInto} methods parse the graph string into a passed graph, which may be a subgraph
|
||||
* <p>
|
||||
* Multiple graphs made for the same entity type can be merged. See {@link EntityGraphs#merge(SessionImplementor, Class, GraphImplementor...)}.
|
||||
* Multiple graphs made for the same entity type can be merged.
|
||||
* See {@link EntityGraphs#merge(EntityManager, Class, jakarta.persistence.Graph...)}.
|
||||
*
|
||||
* @author asusnjar
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user