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
6 changes: 5 additions & 1 deletion hibernate-core/src/main/java/org/hibernate/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import jakarta.persistence.metamodel.EntityType;
import org.hibernate.graph.RootGraph;
import org.hibernate.jdbc.Work;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.hibernate.stat.SessionStatistics;

Expand Down Expand Up @@ -1515,7 +1516,7 @@ public interface Session extends SharedSessionContract, EntityManager {
@Override
<T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass);

// The following overrides should not be necessary,
// The following overrides should not be necessary
// and are only needed to work around a bug in IntelliJ

@Override
Expand All @@ -1527,6 +1528,9 @@ public interface Session extends SharedSessionContract, EntityManager {
@Override @Deprecated @SuppressWarnings("rawtypes")
Query createQuery(String queryString);

@Override @Deprecated @SuppressWarnings("rawtypes")
NativeQuery createNativeQuery(String queryString);

@Override
<R> Query<R> createNamedQuery(String name, Class<R> resultClass);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* Entity graph names must be unique within the persistence unit.
* <p/>
* When applied to a root entity class, the name is optional and
* defaults to the entity-name of that entity.
* defaults to the JPA entity name of that entity.
*/
String name() default "";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
*/
package org.hibernate.boot.model.internal;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.UnknownEntityTypeException;
import org.hibernate.annotations.NamedEntityGraph;
import org.hibernate.boot.model.NamedGraphCreator;
import org.hibernate.grammars.graph.GraphLanguageLexer;
import org.hibernate.grammars.graph.GraphLanguageParser;
import org.hibernate.graph.InvalidGraphException;
import org.hibernate.graph.spi.GraphParserEntityClassResolver;
Expand All @@ -20,6 +17,7 @@
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.metamodel.model.domain.EntityDomainType;

import static org.hibernate.graph.internal.parse.GraphParsing.parseText;
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;

/**
Expand All @@ -44,36 +42,33 @@ class NamedGraphCreatorParsed implements NamedGraphCreator {
public RootGraphImplementor<?> createEntityGraph(
GraphParserEntityClassResolver entityDomainClassResolver,
GraphParserEntityNameResolver entityDomainNameResolver) {
final var lexer = new GraphLanguageLexer( CharStreams.fromString( annotation.graph() ) );
final var parser = new GraphLanguageParser( new CommonTokenStream( lexer ) );
final var graphContext = parser.graph();

final var graphContext = parseText( annotation.graph() );
final var typeIndicator = graphContext.typeIndicator();
final EntityDomainType<?> entityDomainType;
final String jpaEntityName;
if ( entityType == null ) {
if ( typeIndicator == null ) {
throw new InvalidGraphException( "Expecting graph text to include an entity name : " + annotation.graph() );
throw new InvalidGraphException( "Expecting graph text to include an entity name: " + annotation.graph() );
}
final String jpaEntityName = typeIndicator.TYPE_NAME().toString();
final var entityDomainType = entityDomainNameResolver.resolveEntityName( jpaEntityName );
final String name = this.name == null ? jpaEntityName : this.name;
return parse( entityDomainNameResolver, name, entityDomainType, graphContext );
jpaEntityName = typeIndicator.TYPE_NAME().toString();
entityDomainType = entityDomainNameResolver.resolveEntityName( jpaEntityName );
}
else {
if ( typeIndicator != null ) {
throw new InvalidGraphException( "Expecting graph text to not include an entity name : " + annotation.graph() );
throw new InvalidGraphException( "Expecting graph text to not include an entity name: " + annotation.graph() );
}
final var entityDomainType = entityDomainClassResolver.resolveEntityClass( entityType );
final String name = this.name == null ? entityDomainType.getName() : this.name;
return parse( entityDomainNameResolver, name, entityDomainType, graphContext );
entityDomainType = entityDomainClassResolver.resolveEntityClass( entityType );
jpaEntityName = entityDomainType.getName();
}
return visit( name == null ? jpaEntityName : name,
entityDomainType, entityDomainNameResolver, graphContext );
}

private static @NonNull RootGraphImplementor<?> parse(
GraphParserEntityNameResolver entityDomainNameResolver,
private static @NonNull RootGraphImplementor<?> visit(
String name,
EntityDomainType<?> entityDomainType,
EntityDomainType<?> entityDomainType, GraphParserEntityNameResolver entityDomainNameResolver,
GraphLanguageParser.GraphContext graphContext) {
return GraphParsing.parse( name, entityDomainType, graphContext.attributeList(),
return GraphParsing.visit( name, entityDomainType, graphContext.attributeList(),
entityName -> resolve( entityName, entityDomainNameResolver ) );
}

Expand Down
111 changes: 40 additions & 71 deletions hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
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;
Expand Down Expand Up @@ -310,31 +309,10 @@ public static <T> boolean areEqual(EntityGraph<T> a, EntityGraph<T> b) {
if ( a == b ) {
return true;
}
if ( ( a == null ) || ( b == null ) ) {
return false;
}

final List<AttributeNode<?>> aNodes = a.getAttributeNodes();
final List<AttributeNode<?>> bNodes = b.getAttributeNodes();

if ( aNodes.size() != bNodes.size() ) {
return false;
}
for ( AttributeNode<?> aNode : aNodes ) {
final String attributeName = aNode.getAttributeName();
AttributeNode<?> bNode = null;
for ( AttributeNode<?> bCandidate : bNodes ) {
if ( attributeName.equals( bCandidate.getAttributeName() ) ) {
bNode = bCandidate;
break;
}
}
if ( !areEqual( aNode, bNode ) ) {
return false;
}
else {
return a != null && b != null
&& haveSameNodes( a, b );
}

return true;
}

/**
Expand All @@ -345,10 +323,10 @@ public static boolean areEqual(AttributeNode<?> a, AttributeNode<?> b) {
if ( a == b ) {
return true;
}
if ( ( a == null ) || ( b == null ) ) {
else if ( a == null || b == null ) {
return false;
}
if ( a.getAttributeName().equals( b.getAttributeName() ) ) {
else if ( a.getAttributeName().equals( b.getAttributeName() ) ) {
return areEqual( a.getSubgraphs(), b.getSubgraphs() )
&& areEqual( a.getKeySubgraphs(), b.getKeySubgraphs() );
}
Expand All @@ -367,71 +345,62 @@ public static boolean areEqual(
if ( a == b ) {
return true;
}
if ( ( a == null ) || ( b == null ) ) {
else if ( a == null || b == null ) {
return false;
}

@SuppressWarnings("rawtypes")
final Set<Class> aKeys = a.keySet();
@SuppressWarnings("rawtypes")
final Set<Class> bKeys = b.keySet();

if ( aKeys.equals( bKeys ) ) {
for ( Class<?> clazz : aKeys ) {
if ( !bKeys.contains( clazz ) ) {
return false;
}
if ( !areEqual( a.get( clazz ), b.get( clazz ) ) ) {
return false;
else {
final var aKeys = a.keySet();
final var bKeys = b.keySet();
if ( aKeys.equals( bKeys ) ) {
for ( var key : aKeys ) {
if ( !areEqual( a.get( key ), b.get( key ) ) ) {
return false;
}
}
return true;
}
else {
return false;
}
return true;
}
else {
return false;
}
}

/**
* 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(Subgraph<?> a, Subgraph<?> b) {
if ( a == b ) {
return true;
}
if ( ( a == null ) || ( b == null ) ) {
return false;
}
if ( a.getClassType() != b.getClassType() ) {
return false;
else {
return a != null && b != null
&& a.getClassType() == b.getClassType()
&& haveSameNodes( a, b );
}
}

@SuppressWarnings("unchecked")
final List<AttributeNode<?>> aNodes = a.getAttributeNodes();
@SuppressWarnings("unchecked")
final List<AttributeNode<?>> bNodes = b.getAttributeNodes();

private static boolean haveSameNodes(Graph<?> a, Graph<?> b) {
final var aNodes = a.getAttributeNodes();
final var bNodes = b.getAttributeNodes();
if ( aNodes.size() != bNodes.size() ) {
return false;
}

for ( AttributeNode<?> aNode : aNodes ) {
final String attributeName = aNode.getAttributeName();
AttributeNode<?> bNode = null;
for ( AttributeNode<?> bCandidate : bNodes ) {
if ( attributeName.equals( bCandidate.getAttributeName() ) ) {
bNode = bCandidate;
break;
else {
for ( var aNode : aNodes ) {
final String attributeName = aNode.getAttributeName();
AttributeNode<?> bNode = null;
for ( var bCandidate : bNodes ) {
if ( attributeName.equals( bCandidate.getAttributeName() ) ) {
bNode = bCandidate;
break;
}
}
if ( !areEqual( aNode, bNode ) ) {
return false;
}
}
if ( !areEqual( aNode, bNode ) ) {
return false;
}
return true;
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
* The {@link #parse} methods all create a root {@link jakarta.persistence.EntityGraph}
* based on the passed entity class and parse the graph string into that root graph.
* <p>
* The {@link #parseInto} methods parse the graph string into a passed graph, which may be a subgraph
* The {@link #parseInto} methods parse the graph string into a passed graph, which may
* be a subgraph.
* <p>
* Multiple graphs for the same entity type can be
* {@linkplain EntityGraphs#merge(EntityManager, Class, jakarta.persistence.Graph...)
* merged}.
*
* @author asusnjar
*/
@SuppressWarnings("unused")
public final class GraphParser {

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -135,8 +135,8 @@ public static <T> RootGraph<T> parse(
}

/**
* Creates a root graph based on the passed `rootType` and parses `graphText` into
* the generated root graph
* Creates a root graph based on the passed {@code rootType} and parses {@code graphText}
* into the generated root graph.
*
* @apiNote The passed EntityManager is expected to be a Hibernate implementation.
* Attempting to pass another provider's EntityManager implementation will fail.
Expand Down
Loading
Loading