Graphpocalypse: major revision/refactoring of EntityGraph support

- fix up typing issues with key/value subgraphs
This commit is contained in:
Gavin King 2025-01-01 22:05:43 +01:00
parent 5bde39f29c
commit 8509166469
12 changed files with 150 additions and 318 deletions

View File

@ -6,6 +6,7 @@ package org.hibernate.graph;
import java.util.Map;
import org.hibernate.metamodel.model.domain.ManagedDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
/**
@ -19,15 +20,16 @@ public interface AttributeNode<J> extends GraphNode<J>, jakarta.persistence.Attr
PersistentAttribute<?, J> getAttributeDescriptor();
Map<Class<? extends J>, ? extends SubGraph<? extends J>> getSubGraphs();
Map<Class<? extends J>, ? extends SubGraph<? extends J>> getKeySubGraphs();
Map<Class<?>, ? extends SubGraph<?>> getSubGraphs();
Map<Class<?>, ? extends SubGraph<?>> getKeySubGraphs();
<S extends J> void addSubGraph(Class<S> subType, SubGraph<S> subGraph);
<S extends J> void addKeySubGraph(Class<S> subType, SubGraph<S> subGraph);
SubGraph<?> makeSubGraph();
SubGraph<?> makeKeySubGraph();
SubGraph<J> makeSubGraph();
SubGraph<J> makeKeySubGraph();
<S> SubGraph<S> makeSubGraph(Class<S> type);
<S> SubGraph<S> makeKeySubGraph(Class<S> type);
<S> SubGraph<S> makeSubGraph(ManagedDomainType<S> subtype);
<S> SubGraph<S> makeKeySubGraph(ManagedDomainType<S> subtype);
<S extends J> SubGraph<S> makeSubGraph(Class<S> subtype);
<S extends J> SubGraph<S> makeKeySubGraph(Class<S> subtype);
}

View File

@ -188,17 +188,14 @@ public interface Graph<J> extends GraphNode<J>, jakarta.persistence.Graph<J> {
<AJ> SubGraph<AJ> addKeySubGraph(String attributeName);
<AJ> SubGraph<AJ> addKeySubGraph(String attributeName, Class<AJ> type);
<AJ> SubGraph<AJ> addKeySubGraph(PersistentAttribute<? super J,AJ> attribute);
<AJ> SubGraph<AJ> addKeySubGraph(PersistentAttribute<? super J,? super AJ> attribute, Class<AJ> type);
@Override
@Override @Deprecated(forRemoval = true)
default <X> SubGraph<X> addKeySubgraph(Attribute<? super J, X> attribute) {
return addKeySubGraph( (PersistentAttribute<? super J, X>) attribute );
throw new UnsupportedOperationException("This operation will be removed in JPA 4");
}
@Override
@Override @Deprecated(forRemoval = true)
default <X> SubGraph<? extends X> addKeySubgraph(Attribute<? super J, X> attribute, Class<? extends X> type) {
return addKeySubGraph( (PersistentAttribute<? super J, X>) attribute, type );
throw new UnsupportedOperationException("This operation will be removed in JPA 4");
}
@Override

View File

@ -29,7 +29,8 @@ public interface RootGraph<J> extends Graph<J>, EntityGraph<J> {
* @deprecated Planned for removal in JPA 4
*/
@Override @Deprecated(forRemoval = true)
default <T1> SubGraph<? extends T1> addSubclassSubgraph(Class<? extends T1> type) {
throw new UnsupportedOperationException("This operation will be removed in JPA 4");
@SuppressWarnings("unchecked") // The JPA method was defined with an incorrect generic signature
default <T> SubGraph<? extends T> addSubclassSubgraph(Class<? extends T> type) {
return (SubGraph<? extends T>) addTreatedSubgraph( (Class<? extends J>) type );
}
}

View File

@ -37,6 +37,7 @@ import static java.util.Collections.unmodifiableMap;
* @author Steve Ebersole
*/
public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements GraphImplementor<J> {
private final ManagedDomainType<J> managedType;
private Map<PersistentAttribute<? super J,?>, AttributeNodeImplementor<?>> attributeNodes;
@ -109,6 +110,7 @@ public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements G
else {
// we assume the subgraph has been properly copied if needed
node.getSubGraphMap().forEach( (subtype, subgraph) -> attributeNode.addSubGraph( subgraph ) );
node.getKeySubGraphMap().forEach( (subtype, subgraph) -> attributeNode.addKeySubGraph( subgraph ) );
}
}
@ -247,19 +249,19 @@ public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements G
}
@Override
public <AJ> SubGraphImplementor<AJ> addSubGraph(String attributeName, Class<AJ> subType) {
return findOrCreateAttributeNode( attributeName ).makeSubGraph( subType );
public <AJ> SubGraphImplementor<AJ> addSubGraph(String attributeName, Class<AJ> subtype) {
return findOrCreateAttributeNode( attributeName ).makeSubGraph( subtype );
}
@Override
public <AJ> SubGraphImplementor<AJ> addSubGraph(PersistentAttribute<? super J, AJ> attribute) {
return findOrCreateAttributeNode( attribute ).makeSubGraph();
return findOrCreateAttributeNode( attribute ).makeSubGraph( attribute.getJavaType() );
}
@Override
public <AJ> SubGraphImplementor<AJ> addSubGraph(
PersistentAttribute<? super J, ? super AJ> attribute, Class<AJ> subType) {
return findOrCreateAttributeNode( attribute ).makeSubGraph( subType );
PersistentAttribute<? super J, ? super AJ> attribute, Class<AJ> subtype) {
return findOrCreateAttributeNode( attribute ).makeSubGraph( subtype );
}
@Override
@ -280,17 +282,6 @@ public abstract class AbstractGraph<J> extends AbstractGraphNode<J> implements G
return findOrCreateAttributeNode( attributeName ).makeKeySubGraph( subtype );
}
@Override
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(PersistentAttribute<? super J, AJ> attribute) {
return findOrCreateAttributeNode( attribute ).makeKeySubGraph();
}
@Override
public <AJ> SubGraphImplementor<AJ> addKeySubGraph(
PersistentAttribute<? super J, ? super AJ> attribute, Class<AJ> subType) {
return findOrCreateAttributeNode( attribute ).makeKeySubGraph( subType );
}
////////////////// TODO //////////////////
@Override

View File

@ -5,24 +5,15 @@
package org.hibernate.graph.internal;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import org.hibernate.graph.CannotContainSubGraphException;
import org.hibernate.graph.SubGraph;
import org.hibernate.graph.spi.AttributeNodeImplementor;
import org.hibernate.graph.spi.SubGraphImplementor;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.ManagedDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SimpleDomainType;
import org.hibernate.metamodel.model.domain.internal.DomainModelHelper;
import org.jboss.logging.Logger;
import static java.util.Collections.emptyMap;
import static org.hibernate.metamodel.model.domain.internal.DomainModelHelper.findSubType;
/**
* Implementation of {@link jakarta.persistence.AttributeNode}.
@ -34,8 +25,8 @@ public class AttributeNodeImpl<J>
implements AttributeNodeImplementor<J> {
private final PersistentAttribute<?, J> attribute;
private Map<Class<? extends J>, SubGraphImplementor<? extends J>> subgraphMap;
private Map<Class<? extends J>, SubGraphImplementor<? extends J>> keySubgraphMap;
private Map<Class<?>, SubGraphImplementor<?>> subgraphMap;
private Map<Class<?>, SubGraphImplementor<?>> keySubgraphMap;
public <X> AttributeNodeImpl(PersistentAttribute<X, J> attribute, boolean mutable) {
this(attribute, null, null, mutable);
@ -46,8 +37,8 @@ public class AttributeNodeImpl<J>
*/
private AttributeNodeImpl(
PersistentAttribute<?, J> attribute,
Map<Class<? extends J>, SubGraphImplementor<? extends J>> subgraphMap,
Map<Class<? extends J>, SubGraphImplementor<? extends J>> keySubgraphMap,
Map<Class<?>, SubGraphImplementor<?>> subgraphMap,
Map<Class<?>, SubGraphImplementor<?>> keySubgraphMap,
boolean mutable) {
super( mutable );
this.attribute = attribute;
@ -66,164 +57,106 @@ public class AttributeNodeImpl<J>
}
@Override
public Map<Class<? extends J>, SubGraphImplementor<? extends J>> getSubGraphMap() {
public Map<Class<?>, SubGraphImplementor<?>> getSubGraphMap() {
return subgraphMap == null ? emptyMap() : subgraphMap;
}
@Override
public Map<Class<? extends J>, SubGraphImplementor<? extends J>> getKeySubGraphMap() {
public Map<Class<?>, SubGraphImplementor<?>> getKeySubGraphMap() {
return keySubgraphMap == null ? emptyMap() : keySubgraphMap;
}
@Override
public SubGraphImplementor<J> makeSubGraph() {
return internalMakeSubgraph( (Class<J>) null );
public SubGraphImplementor<?> makeSubGraph() {
return makeSubGraph( (ManagedDomainType<?>) attribute.getValueGraphType() );
}
@Override
public <S extends J> SubGraphImplementor<S> makeSubGraph(Class<S> subtype) {
return internalMakeSubgraph( subtype );
public <S> SubGraphImplementor<S> makeSubGraph(Class<S> type) {
return makeSubGraph( attribute.getDeclaringType().getMetamodel().managedType( type ) );
}
@Override
public <S extends J> SubGraphImplementor<S> makeSubGraph(ManagedDomainType<S> subtype) {
return internalMakeSubgraph( subtype );
}
private <S extends J> SubGraphImplementor<S> internalMakeSubgraph(ManagedDomainType<S> type) {
assert type != null;
log.debugf( "Making subgraph : ( (%s) %s )", type.getTypeName(), getAttributeName() );
final SubGraphImplementor<S> subGraph = DomainModelHelper.makeSubGraph( type, type.getBindableJavaType() );
internalAddSubGraph( subGraph );
public <S> SubGraphImplementor<S> makeSubGraph(ManagedDomainType<S> subtype) {
verifyMutability();
assert subtype != null;
if ( !attribute.getValueGraphType().getBindableJavaType().isAssignableFrom( subtype.getJavaType() ) ) {
throw new IllegalArgumentException( "Not a subtype: " + subtype.getJavaType() );
}
final SubGraphImplementor<S> subGraph = new SubGraphImpl<>( subtype, true );
addSubGraph( subGraph );
return subGraph;
}
@SuppressWarnings("unchecked")
private <T extends J> ManagedDomainType<T> valueGraphTypeAsManaged() {
final DomainType<?> valueGraphType = getAttributeDescriptor().getValueGraphType();
if ( valueGraphType instanceof ManagedDomainType ) {
return (ManagedDomainType<T>) valueGraphType;
}
else {
throw new CannotContainSubGraphException(
String.format(
Locale.ROOT,
"Attribute [%s] (%s) cannot contain value subgraphs",
getAttributeName(),
getAttributeDescriptor().getPersistentAttributeType().name()
)
);
}
}
private static final Logger log = Logger.getLogger( AttributeNodeImpl.class );
private <S extends J> SubGraphImplementor<S> internalMakeSubgraph(Class<S> subType) {
verifyMutability();
final ManagedDomainType<S> managedType = valueGraphTypeAsManaged();
return internalMakeSubgraph( findSubType( managedType, subType == null ? managedType.getJavaType() : subType ) );
}
protected void internalAddSubGraph(SubGraphImplementor<? extends J> subGraph) {
log.tracef( "Adding subgraph : ( (%s) %s )", subGraph.getGraphedType().getTypeName(), getAttributeName() );
@Override
public void addSubGraph(SubGraphImplementor<?> subgraph) {
if ( subgraphMap == null ) {
subgraphMap = new HashMap<>();
}
final SubGraphImplementor<? extends J> previous = subgraphMap.put( subGraph.getClassType(), subGraph );
if ( previous != null ) {
log.debugf( "Adding subgraph [%s] over-wrote existing [%s]", subGraph, previous );
}
}
@Override
public <S extends J> void addSubGraph(Class<S> subType, SubGraph<S> subGraph) {
verifyMutability();
assert subGraph.getClassType() == subType;
internalAddSubGraph( (SubGraphImplementor<S>) subGraph );
}
@Override
public void addSubGraph(SubGraphImplementor<? extends J> subgraph) {
internalAddSubGraph( subgraph );
}
@Override
public SubGraphImplementor<J> makeKeySubGraph() {
return internalMakeKeySubgraph( (Class<J>) null );
}
@Override
public <S extends J> SubGraphImplementor<S> makeKeySubGraph(Class<S> subtype) {
return internalMakeKeySubgraph( subtype );
}
@Override
public <S extends J> SubGraphImplementor<S> makeKeySubGraph(ManagedDomainType<S> subtype) {
return internalMakeKeySubgraph( subtype );
}
private <S extends J> SubGraphImplementor<S> internalMakeKeySubgraph(ManagedDomainType<S> type) {
assert type != null;
log.debugf( "Making key subgraph : ( (%s) %s )", type.getTypeName(), getAttributeName() );
final SubGraphImplementor<S> subGraph = DomainModelHelper.makeSubGraph( type, type.getBindableJavaType() );
internalAddKeySubGraph( subGraph );
return subGraph;
}
private <S extends J> SubGraphImplementor<S> internalMakeKeySubgraph(Class<S> type) {
verifyMutability();
final ManagedDomainType<S> managedType = keyGraphTypeAsManaged();
return internalMakeKeySubgraph( type == null ? managedType : findSubType( managedType, type ) );
}
protected void internalAddKeySubGraph(SubGraph<? extends J> subGraph) {
log.tracef( "Adding key subgraph : ( (%s) %s )", subGraph.getClassType().getName(), getAttributeName() );
if ( keySubgraphMap == null ) {
keySubgraphMap = new HashMap<>();
}
final SubGraphImplementor<? extends J> previous =
keySubgraphMap.put( subGraph.getClassType(), (SubGraphImplementor<? extends J>) subGraph );
if ( previous != null ) {
log.debugf( "Adding key subgraph [%s] overwrote existing [%]", subGraph, previous );
}
}
@SuppressWarnings("unchecked")
private <T extends J> ManagedDomainType<T> keyGraphTypeAsManaged() {
final SimpleDomainType<?> keyGraphType = getAttributeDescriptor().getKeyGraphType();
if ( keyGraphType instanceof ManagedDomainType ) {
return (ManagedDomainType<T>) keyGraphType;
subgraphMap.put( subgraph.getClassType(), subgraph );
}
else {
throw new CannotContainSubGraphException(
String.format(
Locale.ROOT,
"Attribute [%s#%s] (%s) cannot contain key subgraphs - %s",
getAttributeDescriptor().getDeclaringType().getTypeName(),
getAttributeName(),
getAttributeDescriptor().getPersistentAttributeType().name(),
keyGraphType
)
);
final SubGraphImplementor<?> existing = subgraphMap.get( subgraph.getClassType() );
if ( existing == null ) {
subgraphMap.put( subgraph.getClassType(), subgraph );
}
else {
existing.merge( (SubGraphImplementor) subgraph );
}
}
}
@Override
public <S extends J> void addKeySubGraph(Class<S> subType, SubGraph<S> subGraph) {
assert subGraph.getClassType() == subType;
internalAddKeySubGraph( subGraph );
public void addKeySubGraph(SubGraphImplementor<?> subgraph) {
if ( keySubgraphMap == null ) {
keySubgraphMap = new HashMap<>();
keySubgraphMap.put( subgraph.getClassType(), subgraph );
}
else {
final SubGraphImplementor<?> existing = keySubgraphMap.get( subgraph.getClassType() );
if ( existing == null ) {
keySubgraphMap.put( subgraph.getClassType(), subgraph );
}
else {
existing.merge( (SubGraphImplementor) subgraph );
}
}
}
@Override
public SubGraphImplementor<?> makeKeySubGraph() {
return makeKeySubGraph( (ManagedDomainType<?>) attribute.getKeyGraphType() );
}
@Override
public <S> SubGraphImplementor<S> makeKeySubGraph(Class<S> type) {
return makeKeySubGraph( attribute.getDeclaringType().getMetamodel().managedType( type ) );
}
@Override
public <S> SubGraphImplementor<S> makeKeySubGraph(ManagedDomainType<S> subtype) {
verifyMutability();
assert subtype != null;
if ( !attribute.getKeyGraphType().getBindableJavaType().isAssignableFrom( subtype.getJavaType() ) ) {
throw new IllegalArgumentException( "Not a key subtype: " + subtype.getJavaType() );
}
final SubGraphImplementor<S> subgraph = new SubGraphImpl<>( subtype, true );
addKeySubGraph( subgraph );
return subgraph;
}
@Override
public AttributeNodeImplementor<J> makeCopy(boolean mutable) {
return new AttributeNodeImpl<>(
this.attribute, makeMapCopy( mutable, subgraphMap ), makeMapCopy( mutable, keySubgraphMap ), mutable
this.attribute,
makeMapCopy( mutable, subgraphMap ),
makeMapCopy( mutable, keySubgraphMap ),
mutable
);
}
private Map<Class<? extends J>, SubGraphImplementor<? extends J>> makeMapCopy(
private <U,V> Map<Class<? extends U>, SubGraphImplementor<? extends V>> makeMapCopy(
boolean mutable,
Map<Class<? extends J>, SubGraphImplementor<? extends J>> nodeMap) {
Map<Class<? extends U>, SubGraphImplementor<? extends V>> nodeMap) {
if ( nodeMap == null ) {
return null;
}
@ -240,23 +173,23 @@ public class AttributeNodeImpl<J>
other.getKeySubGraphMap().values().forEach( this::mergeToKeySubgraph );
}
private <T extends J> void mergeToKeySubgraph(SubGraphImplementor<T> subgraph) {
private <T> void mergeToKeySubgraph(SubGraphImplementor<T> subgraph) {
final SubGraphImplementor<T> existing = getKeySubgraphForPut( subgraph );
if ( existing != null ) {
existing.merge( subgraph );
}
else {
internalAddKeySubGraph( subgraph.makeCopy( true ) );
addKeySubGraph( subgraph.makeCopy( true ) );
}
}
private <T extends J> void mergeToSubgraph(SubGraphImplementor<T> subgraph) {
private <T> void mergeToSubgraph(SubGraphImplementor<T> subgraph) {
final SubGraphImplementor<T> existing = getSubgraphForPut( subgraph );
if ( existing != null ) {
existing.merge( subgraph );
}
else {
internalAddSubGraph( subgraph.makeCopy( true ) );
addSubGraph( subgraph.makeCopy( true ) );
}
}

View File

@ -4,57 +4,42 @@
*/
package org.hibernate.graph.internal.parse;
import org.hibernate.graph.CannotContainSubGraphException;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.ManagedDomainType;
import static org.hibernate.metamodel.model.domain.internal.DomainModelHelper.resolveSubType;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("unchecked")
public enum PathQualifierType {
KEY(
(attributeNode, subTypeName, sessionFactory) ->
attributeNode.makeKeySubGraph(
resolveSubTypeManagedType(
attributeNode.getAttributeDescriptor().getKeyGraphType(),
subTypeName,
sessionFactory.getJpaMetamodel()
)
)
KEY( (attributeNode, subtypeName, sessionFactory) -> subtypeName == null
? attributeNode.makeKeySubGraph()
: attributeNode.makeKeySubGraph( getSubtype( subtypeName, sessionFactory ) )
),
VALUE(
(attributeNode, subTypeName, sessionFactory) ->
attributeNode.makeSubGraph(
resolveSubTypeManagedType(
attributeNode.getAttributeDescriptor().getValueGraphType(),
subTypeName,
sessionFactory.getJpaMetamodel()
)
)
VALUE( (attributeNode, subtypeName, sessionFactory) -> subtypeName == null
? attributeNode.makeSubGraph()
: attributeNode.makeSubGraph( getSubtype( subtypeName, sessionFactory ) )
);
private static ManagedDomainType resolveSubTypeManagedType(
DomainType<?> graphType,
String subTypeName,
JpaMetamodel metamodel) {
if ( !( graphType instanceof ManagedDomainType<?> managedType ) ) {
throw new CannotContainSubGraphException( "The given type [" + graphType + "] is not a ManagedType" );
private static ManagedDomainType<?> getSubtype(String subtypeName, SessionFactoryImplementor sessionFactory) {
final JpaMetamodel metamodel = sessionFactory.getJpaMetamodel();
ManagedDomainType<?> managedType = metamodel.findManagedType( subtypeName );
if ( managedType == null ) {
managedType = metamodel.getHqlEntityReference( subtypeName );
}
if ( subTypeName != null ) {
managedType = resolveSubType( managedType, subTypeName, metamodel );
if ( managedType == null ) {
throw new IllegalArgumentException( "Unknown type " + subtypeName );
}
return managedType;
}
private final SubGraphGenerator subGraphCreator;
PathQualifierType(SubGraphGenerator subGraphCreator) {
this.subGraphCreator = subGraphCreator;
PathQualifierType(SubGraphGenerator subgraphCreator) {
this.subGraphCreator = subgraphCreator;
}
public SubGraphGenerator getSubGraphCreator() {

View File

@ -22,16 +22,16 @@ import static java.util.Collections.unmodifiableMap;
*/
public interface AttributeNodeImplementor<J> extends AttributeNode<J>, GraphNodeImplementor<J> {
Map<Class<? extends J>, SubGraphImplementor<? extends J>> getSubGraphMap();
Map<Class<? extends J>, SubGraphImplementor<? extends J>> getKeySubGraphMap();
Map<Class<?>, SubGraphImplementor<?>> getSubGraphMap();
Map<Class<?>, SubGraphImplementor<?>> getKeySubGraphMap();
@Override
default Map<Class<? extends J>, ? extends SubGraph<? extends J>> getSubGraphs() {
default Map<Class<?>, ? extends SubGraph<?>> getSubGraphs() {
return unmodifiableMap( getSubGraphMap() );
}
@Override
default Map<Class<? extends J>, ? extends SubGraph<? extends J>> getKeySubGraphs() {
default Map<Class<?>, ? extends SubGraph<?>> getKeySubGraphs() {
return unmodifiableMap( getKeySubGraphMap() );
}
@ -49,22 +49,26 @@ public interface AttributeNodeImplementor<J> extends AttributeNode<J>, GraphNode
AttributeNodeImplementor<J> makeCopy(boolean mutable);
@Override
SubGraphImplementor<J> makeSubGraph();
SubGraphImplementor<?> makeSubGraph();
@Override
SubGraphImplementor<J> makeKeySubGraph();
SubGraphImplementor<?> makeKeySubGraph();
@Override
<S extends J> SubGraphImplementor<S> makeSubGraph(Class<S> subtype);
<S> SubGraphImplementor<S> makeSubGraph(Class<S> type);
@Override
<S extends J> SubGraphImplementor<S> makeKeySubGraph(Class<S> subtype);
<S> SubGraphImplementor<S> makeKeySubGraph(Class<S> type);
<S extends J> SubGraphImplementor<S> makeSubGraph(ManagedDomainType<S> subtype);
@Override
<S> SubGraphImplementor<S> makeSubGraph(ManagedDomainType<S> subtype);
<S extends J> SubGraphImplementor<S> makeKeySubGraph(ManagedDomainType<S> subtype);
@Override
<S> SubGraphImplementor<S> makeKeySubGraph(ManagedDomainType<S> subtype);
void merge(AttributeNodeImplementor<J> other);
void addSubGraph(SubGraphImplementor<? extends J> subgraph);
void addSubGraph(SubGraphImplementor<?> subgraph);
void addKeySubGraph(SubGraphImplementor<?> subgraph);
}

View File

@ -84,10 +84,4 @@ public interface GraphImplementor<J> extends Graph<J>, GraphNodeImplementor<J> {
@Override
<AJ> SubGraphImplementor<AJ> addKeySubGraph(String attributeName, Class<AJ> subtype);
@Override
<AJ> SubGraphImplementor<AJ> addKeySubGraph(PersistentAttribute<? super J, AJ> attribute);
@Override
<AJ> SubGraphImplementor<AJ> addKeySubGraph(PersistentAttribute<? super J, ? super AJ> attribute, Class<AJ> subtype);
}

View File

@ -4,15 +4,10 @@
*/
package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.graph.internal.SubGraphImpl;
import org.hibernate.graph.spi.SubGraphImplementor;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.ManagedDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
@ -25,35 +20,6 @@ import static org.hibernate.metamodel.mapping.MappingModelHelper.isCompatibleMod
*/
public class DomainModelHelper {
@SuppressWarnings("unchecked")
public static <T, S extends T> ManagedDomainType<S> resolveSubType(
ManagedDomainType<T> baseType,
String subTypeName,
JpaMetamodel jpaMetamodel) {
if ( baseType instanceof EmbeddableDomainType<?> ) {
// todo : at least validate the string is a valid subtype of the embeddable class?
return (ManagedDomainType<S>) baseType;
}
// first, try to find it by name directly
final ManagedDomainType<S> subManagedType = jpaMetamodel.resolveHqlEntityReference( subTypeName );
if ( subManagedType != null ) {
return subManagedType;
}
// it could still be a mapped-superclass
try {
final Class<?> javaType =
jpaMetamodel.getServiceRegistry().requireService( ClassLoaderService.class )
.classForName( subTypeName );
return (ManagedDomainType<S>) jpaMetamodel.managedType( javaType );
}
catch (Exception ignore) {
}
throw new IllegalArgumentException( "Unknown subtype name (" + baseType.getTypeName() + ") : " + subTypeName );
}
static boolean isCompatible(
PersistentAttribute<?, ?> attribute1,
PersistentAttribute<?, ?> attribute2,
@ -94,43 +60,4 @@ public class DomainModelHelper {
return candidate;
}
}
public static <J, S> ManagedDomainType<S> findSubType(ManagedDomainType<J> type, Class<S> subtype) {
if ( type.getBindableJavaType() == subtype ) {
@SuppressWarnings("unchecked")
final ManagedDomainType<S> result = (ManagedDomainType<S>) type;
return result;
}
for ( ManagedDomainType<? extends J> candidate : type.getSubTypes() ) {
if ( candidate.getBindableJavaType() == subtype ) {
@SuppressWarnings("unchecked")
final ManagedDomainType<S> result = (ManagedDomainType<S>) candidate;
return result;
}
}
for ( ManagedDomainType<? extends J> candidate : type.getSubTypes() ) {
final ManagedDomainType<S> candidateSubtype = findSubType( candidate, subtype );
if ( candidateSubtype != null) {
return candidateSubtype;
}
}
throw new IllegalArgumentException( "The class '" + subtype.getName()
+ "' is not a mapped subtype of '" + type.getTypeName() + "'" );
// return metamodel.managedType( subtype );
}
public static <J, S> SubGraphImplementor<S> makeSubGraph(ManagedDomainType<J> type, Class<S> subtype) {
if ( type.getBindableJavaType().isAssignableFrom( subtype ) ) {
return new SubGraphImpl( type, true );
}
else {
throw new IllegalArgumentException(
String.format(
"Type '%s' cannot be treated as subtype '%s'",
type.getTypeName(),
subtype.getName()
)
);
}
}
}

View File

@ -320,16 +320,20 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
if ( enumJavaType != null ) {
return enumJavaType;
}
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
try {
final Class<Object> clazz = classLoaderService.classForName( className );
if ( clazz == null || !clazz.isEnum() ) {
return null;
else {
final ClassLoaderService classLoaderService =
serviceRegistry.requireService( ClassLoaderService.class );
try {
final Class<?> clazz = classLoaderService.classForName( className );
if ( clazz == null || !clazz.isEnum() ) {
return null;
}
//noinspection rawtypes,unchecked
return new EnumJavaType( clazz );
}
catch (ClassLoadingException e) {
throw new RuntimeException( e );
}
return new EnumJavaType( clazz );
}
catch (ClassLoadingException e) {
throw new RuntimeException( e );
}
}

View File

@ -6,7 +6,6 @@ package org.hibernate.sql.results.graph;
import org.hibernate.Incubating;
import org.hibernate.engine.FetchTiming;
import org.hibernate.graph.AttributeNode;
import org.hibernate.graph.spi.GraphImplementor;
/**
@ -59,14 +58,8 @@ public interface EntityGraphTraversalState {
}
/**
* Traverses to the next part of the Jakarta Persistence entity graph relating to the
* given fetchable.
* <p>
*
* The {@link AttributeNode} corresponding to the given `fetchable` is resolved.
*
* Depending on `exploreKeySubgraph`, either {@link AttributeNode#getSubGraphs()}
* or {@link AttributeNode#getKeySubGraphs()} will be used
* Traverses to the next part of the Jakarta Persistence entity graph relating to
* the given {@link Fetchable}.
*/
TraversalResult traverse(FetchParent parent, Fetchable fetchable, boolean exploreKeySubgraph);

View File

@ -14,14 +14,15 @@ import org.junit.Test;
public class EntityGraphsTest extends AbstractEntityGraphTest {
private final <T> void checkMerge(Class<T> rootType, EntityGraph<T> expected, @SuppressWarnings("unchecked") EntityGraph<T>... graphs) {
@SafeVarargs
private <T> void checkMerge(Class<T> rootType, EntityGraph<T> expected, EntityGraph<T>... graphs) {
EntityManager entityManager = getOrCreateEntityManager();
EntityGraph<T> actual = EntityGraphs.merge( entityManager, rootType, graphs );
Assert.assertTrue( EntityGraphs.areEqual( expected, actual ) );
}
@SafeVarargs
private final void checkMerge(EntityGraph<GraphParsingTestEntity> expected, EntityGraph<GraphParsingTestEntity>... graphs) {
private void checkMerge(EntityGraph<GraphParsingTestEntity> expected, EntityGraph<GraphParsingTestEntity>... graphs) {
checkMerge( GraphParsingTestEntity.class, expected, graphs );
}