Graphpocalypse: major revision/refactoring of EntityGraph support
- fix up typing issues with key/value subgraphs
This commit is contained in:
parent
5bde39f29c
commit
8509166469
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue