HHH-15442 Allow for setParameter usage with a queries for a specific type in an Any-discriminated relationship
This commit is contained in:
parent
bc94357d4a
commit
863f045bf8
|
@ -115,6 +115,7 @@ public class DiscriminatedAssociationAttributeMapping
|
|||
return discriminatorMapping.resolveDiscriminatorValueToEntityMapping( discriminatorValue );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveDiscriminatorForEntityType(EntityMappingType entityMappingType) {
|
||||
return discriminatorMapping.resolveDiscriminatorValueToEntityMapping( entityMappingType );
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain;
|
||||
|
||||
|
||||
/**
|
||||
* Models Hibernate's ANY mapping (reverse discrimination) as a JPA domain model type
|
||||
*
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.MetaType;
|
||||
import org.hibernate.type.descriptor.java.ClassJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
public class AnyDiscriminatorDomainTypeImpl<T>
|
||||
implements SimpleDomainType<T>, MappingModelExpressible<T>, BasicValueConverter<T, Object> {
|
||||
private final BasicType underlyingType;
|
||||
private final MetaType modelPart;
|
||||
|
||||
public AnyDiscriminatorDomainTypeImpl(BasicType<?> underlyingType, MetaType modelPart) {
|
||||
this.underlyingType = underlyingType;
|
||||
this.modelPart = modelPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T toDomainValue(Object discriminatorValue) {
|
||||
if ( discriminatorValue == null ) {
|
||||
return null;
|
||||
}
|
||||
return (T) modelPart.getDiscriminatorValuesToEntityNameMap().get( discriminatorValue );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toRelationalValue(T domainForm) {
|
||||
if ( domainForm == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( domainForm instanceof Class ) {
|
||||
return modelPart.getEntityNameToDiscriminatorValueMap().get( ( (Class) domainForm ).getName() );
|
||||
}
|
||||
else {
|
||||
return modelPart.getEntityNameToDiscriminatorValueMap().get( (String) domainForm );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<T> getDomainJavaType() {
|
||||
return getExpressibleJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<Object> getRelationalJavaType() {
|
||||
return underlyingType.getExpressibleJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.BASIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getJavaType() {
|
||||
return Class.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
||||
return toRelationalValue( (T) value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachDisassembledJdbcValue(
|
||||
Object value,
|
||||
Clause clause,
|
||||
int offset,
|
||||
JdbcValuesConsumer valuesConsumer,
|
||||
SharedSessionContractImplementor session) {
|
||||
valuesConsumer.consume( offset, value, underlyingType );
|
||||
return 1;
|
||||
}
|
||||
|
||||
public JavaType<T> getExpressibleJavaType() {
|
||||
return (JavaType<T>) ClassJavaType.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
|
||||
action.accept( 0, underlyingType );
|
||||
return 1;
|
||||
}
|
||||
|
||||
public BasicType getBasicType() {
|
||||
return underlyingType;
|
||||
}
|
||||
}
|
|
@ -12,25 +12,24 @@ import org.hibernate.query.PathException;
|
|||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.AbstractSqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
|
||||
public class AnyDiscriminatorSqmPath extends AbstractSqmPath {
|
||||
public class AnyDiscriminatorSqmPath<T> extends AbstractSqmPath<T> {
|
||||
|
||||
protected AnyDiscriminatorSqmPath(
|
||||
NavigablePath navigablePath,
|
||||
SqmPathSource referencedPathSource,
|
||||
AnyDiscriminatorSqmPathSource referencedPathSource,
|
||||
SqmPath lhs,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( navigablePath, referencedPathSource, lhs, nodeBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnyDiscriminatorSqmPath copy(SqmCopyContext context) {
|
||||
public AnyDiscriminatorSqmPath<T> copy(SqmCopyContext context) {
|
||||
final AnyDiscriminatorSqmPath existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
|
@ -67,4 +66,15 @@ public class AnyDiscriminatorSqmPath extends AbstractSqmPath {
|
|||
public SqmTreatedPath treatAs(EntityDomainType treatTarget) throws PathException {
|
||||
throw new UnsupportedMappingException( "Cannot apply TREAT operator to discriminator path" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<T> getLhs() {
|
||||
return (SqmPath<T>) super.getLhs().getLhs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnyDiscriminatorSqmPathSource<T> getExpressible() {
|
||||
return (AnyDiscriminatorSqmPathSource<T>) getNodeType();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
* SqmPathSource implementation for {@link org.hibernate.annotations.AnyDiscriminator}
|
||||
|
@ -19,10 +20,9 @@ import org.hibernate.spi.NavigablePath;
|
|||
public class AnyDiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
||||
implements ReturnableType<D> {
|
||||
|
||||
|
||||
public AnyDiscriminatorSqmPathSource(
|
||||
String localPathName,
|
||||
SimpleDomainType domainType,
|
||||
AnyDiscriminatorDomainTypeImpl domainType,
|
||||
BindableType jpaBindableType) {
|
||||
super( localPathName, domainType, jpaBindableType );
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class AnyDiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
|||
@Override
|
||||
public SqmPath<D> createSqmPath(SqmPath<?> lhs, SqmPathSource<?> intermediatePathSource) {
|
||||
final NavigablePath navigablePath;
|
||||
if ( intermediatePathSource == null ) {
|
||||
if ( intermediatePathSource == null || intermediatePathSource.getPathName().equals( CollectionPart.Nature.ELEMENT.getName() ) ) {
|
||||
navigablePath = lhs.getNavigablePath();
|
||||
}
|
||||
else {
|
||||
|
@ -54,4 +54,13 @@ public class AnyDiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
|||
return getExpressibleJavaType().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnyDiscriminatorDomainTypeImpl<D> getSqmPathType() {
|
||||
return (AnyDiscriminatorDomainTypeImpl<D>) super.getSqmPathType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<D> getExpressibleJavaType() {
|
||||
return getSqmPathType().getExpressibleJavaType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,15 @@ import org.hibernate.type.descriptor.java.JavaType;
|
|||
public class AnyMappingDomainTypeImpl<T> implements AnyMappingDomainType<T> {
|
||||
private final AnyType anyType;
|
||||
private final JavaType<T> baseJtd;
|
||||
private final AnyDiscriminatorDomainTypeImpl<?> anyDiscriminatorType;
|
||||
|
||||
public AnyMappingDomainTypeImpl(AnyType anyType, JavaType<T> baseJtd) {
|
||||
this.anyType = anyType;
|
||||
this.baseJtd = baseJtd;
|
||||
final MetaType discriminatorType = (MetaType) anyType.getDiscriminatorType();
|
||||
anyDiscriminatorType = new AnyDiscriminatorDomainTypeImpl<>(
|
||||
(BasicType<?>) discriminatorType.getBaseType(),
|
||||
discriminatorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,8 +46,8 @@ public class AnyMappingDomainTypeImpl<T> implements AnyMappingDomainType<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SimpleDomainType<?> getDiscriminatorType() {
|
||||
return (SimpleDomainType<?>) ((MetaType) anyType.getDiscriminatorType()).getBaseType();
|
||||
public AnyDiscriminatorDomainTypeImpl<?> getDiscriminatorType() {
|
||||
return anyDiscriminatorType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,7 +29,10 @@ public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> {
|
|||
BindableType jpaBindableType) {
|
||||
super( localPathName, domainType, jpaBindableType );
|
||||
keyPathSource = new BasicSqmPathSource<>( "id", (BasicDomainType<?>) domainType.getKeyType(), SINGULAR_ATTRIBUTE );
|
||||
discriminatorPathSource = new AnyDiscriminatorSqmPathSource<>( localPathName, domainType.getDiscriminatorType(), jpaBindableType );
|
||||
discriminatorPathSource = new AnyDiscriminatorSqmPathSource<>(
|
||||
localPathName,
|
||||
(AnyDiscriminatorDomainTypeImpl) domainType.getDiscriminatorType(), jpaBindableType
|
||||
);
|
||||
}
|
||||
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
|
|
|
@ -2155,16 +2155,12 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
private <T> SqmExpression<T> createDiscriminatorValue(
|
||||
AnyDiscriminatorSqmPath anyDiscriminatorTypeSqmPath,
|
||||
HqlParser.ExpressionContext valueExpressionContext) {
|
||||
//noinspection unchecked
|
||||
final SqmPath<T> discriminatorSqmPath = anyDiscriminatorTypeSqmPath.getLhs();
|
||||
final EntityDomainType<T> entityWithDiscriminator = creationContext.getJpaMetamodel()
|
||||
.entity( discriminatorSqmPath.findRoot().getNavigablePath().getLocalName() );
|
||||
final EntityDomainType<Object> entityDiscriminatorValue = creationContext.getJpaMetamodel()
|
||||
.resolveHqlEntityReference( valueExpressionContext.getText() );
|
||||
return new SqmAnyDiscriminatorValue<>(
|
||||
entityWithDiscriminator,
|
||||
discriminatorSqmPath.getNodeType().getPathName(),
|
||||
entityDiscriminatorValue,
|
||||
creationContext.getJpaMetamodel()
|
||||
.entity( anyDiscriminatorTypeSqmPath.findRoot().getNavigablePath().getLocalName() ),
|
||||
anyDiscriminatorTypeSqmPath.getNodeType().getPathName(),
|
||||
creationContext.getJpaMetamodel().resolveHqlEntityReference( valueExpressionContext.getText() ),
|
||||
anyDiscriminatorTypeSqmPath.getExpressible().getSqmPathType(),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.Bindable;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
||||
|
@ -84,7 +83,6 @@ import org.hibernate.metamodel.mapping.SelectableMappings;
|
|||
import org.hibernate.metamodel.mapping.SqlExpressible;
|
||||
import org.hibernate.metamodel.mapping.SqlTypedMapping;
|
||||
import org.hibernate.metamodel.mapping.ValueMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
|
||||
import org.hibernate.metamodel.mapping.internal.SqlTypedMappingImpl;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
|
@ -99,6 +97,8 @@ import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
|||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorDomainTypeImpl;
|
||||
import org.hibernate.query.derived.AnonymousTupleTableGroupProducer;
|
||||
import org.hibernate.query.derived.AnonymousTupleType;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||
|
@ -5170,6 +5170,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
throw new NotYetImplementedFor6Exception( "Support for embedded-valued parameters not yet implemented" );
|
||||
}
|
||||
|
||||
if ( paramSqmType instanceof AnyDiscriminatorSqmPathSource ) {
|
||||
return (MappingModelExpressible<?>) ((AnyDiscriminatorSqmPathSource)paramSqmType).getSqmPathType();
|
||||
}
|
||||
|
||||
if ( paramSqmType instanceof SqmPathSource<?> || paramSqmType instanceof BasicDomainType<?> ) {
|
||||
// Try to infer the value mapping since the other side apparently is a path source
|
||||
final MappingModelExpressible<?> inferredValueMapping = getInferredValueMapping();
|
||||
|
@ -6233,50 +6237,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
@Override
|
||||
public Expression visitAnyDiscriminatorTypeValueExpression(SqmAnyDiscriminatorValue expression) {
|
||||
final EntityPersister mappingDescriptor = creationContext.getSessionFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.getEntityDescriptor( ((EntityDomainType)expression.getNodeType()).getHibernateEntityName() );
|
||||
for ( AttributeMapping attributeMapping : mappingDescriptor.getAttributeMappings() ) {
|
||||
if ( attributeMapping instanceof EmbeddedAttributeMapping ) {
|
||||
final ModelPart subPart = ( (EmbeddedAttributeMapping) attributeMapping ).findSubPart(
|
||||
expression.getPathName(),
|
||||
null
|
||||
);
|
||||
if ( subPart != null ) {
|
||||
return buildQueryLiteral( expression, subPart );
|
||||
}
|
||||
}
|
||||
else if ( attributeMapping.getAttributeName().equals( expression.getPathName() ) ) {
|
||||
return buildQueryLiteral( expression, attributeMapping );
|
||||
}
|
||||
}
|
||||
throw new HibernateException(String.format(
|
||||
Locale.ROOT,
|
||||
"Could not locate attribute mapping : %s -> %s",
|
||||
mappingDescriptor.getEntityName(),
|
||||
expression.getPathName()
|
||||
));
|
||||
}
|
||||
|
||||
private QueryLiteral<Object> buildQueryLiteral(
|
||||
SqmAnyDiscriminatorValue expression,
|
||||
ModelPart attributeMapping) {
|
||||
final DiscriminatedAssociationModelPart discriminatedAssociationModelPart;
|
||||
if ( attributeMapping instanceof PluralAttributeMapping ) {
|
||||
discriminatedAssociationModelPart = (DiscriminatedAssociationModelPart) ( (PluralAttributeMapping) attributeMapping ).getElementDescriptor();
|
||||
}
|
||||
else {
|
||||
assert attributeMapping instanceof DiscriminatedAssociationModelPart;
|
||||
discriminatedAssociationModelPart = (DiscriminatedAssociationModelPart) attributeMapping;
|
||||
}
|
||||
final Object value = discriminatedAssociationModelPart.resolveDiscriminatorForEntityType(
|
||||
creationContext.getMappingMetamodel()
|
||||
.findEntityDescriptor( expression.getEntityValue().getHibernateEntityName() ) );
|
||||
|
||||
final AnyDiscriminatorDomainTypeImpl domainType = expression.getDomainType();
|
||||
return new QueryLiteral<>(
|
||||
value,
|
||||
discriminatedAssociationModelPart.getDiscriminatorPart()
|
||||
domainType.toRelationalValue( expression.getEntityValue().getHibernateEntityName() ),
|
||||
domainType.getBasicType()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,9 +32,9 @@ public class DiscriminatedAssociationTypePathInterpretation<T> extends AbstractS
|
|||
AnyDiscriminatorSqmPath sqmPath,
|
||||
SqmToSqlAstConverter converter) {
|
||||
final SqmPath lhs = sqmPath.getLhs();
|
||||
final TableGroup tableGroup = converter.getFromClauseAccess().findTableGroup( lhs.getLhs().getNavigablePath() );
|
||||
final TableGroup tableGroup = converter.getFromClauseAccess().findTableGroup( lhs.getNavigablePath() );
|
||||
final ModelPart subPart = tableGroup.getModelPart().findSubPart(
|
||||
lhs.getNavigablePath().getLocalName(),
|
||||
sqmPath.getNavigablePath().getLocalName(),
|
||||
null
|
||||
);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorDomainTypeImpl;
|
||||
import org.hibernate.query.hql.HqlInterpretationException;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
|
@ -20,16 +21,23 @@ public class SqmAnyDiscriminatorValue<T> extends AbstractSqmExpression<T>
|
|||
implements SqmSelectableNode<T>, SemanticPathPart {
|
||||
|
||||
private final EntityDomainType value;
|
||||
private final AnyDiscriminatorDomainTypeImpl domainType;
|
||||
private final String pathName;
|
||||
|
||||
public SqmAnyDiscriminatorValue(
|
||||
EntityDomainType<T> entityWithDiscriminator,
|
||||
String pathName,
|
||||
EntityDomainType entityValue,
|
||||
AnyDiscriminatorDomainTypeImpl domainType,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( entityWithDiscriminator, nodeBuilder );
|
||||
this.value = entityValue;
|
||||
this.pathName = pathName;
|
||||
this.domainType = domainType;
|
||||
}
|
||||
|
||||
public AnyDiscriminatorDomainTypeImpl getDomainType(){
|
||||
return domainType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,6 +52,7 @@ public class SqmAnyDiscriminatorValue<T> extends AbstractSqmExpression<T>
|
|||
(EntityDomainType) getNodeType(),
|
||||
pathName,
|
||||
value,
|
||||
domainType,
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
|
|
|
@ -49,6 +49,10 @@ public class MetaType extends AbstractType {
|
|||
return discriminatorValuesToEntityNameMap;
|
||||
}
|
||||
|
||||
public Map<String,Object> getEntityNameToDiscriminatorValueMap(){
|
||||
return entityNameToDiscriminatorValueMap;
|
||||
}
|
||||
|
||||
public int[] getSqlTypeCodes(Mapping mapping) throws MappingException {
|
||||
return baseType.getSqlTypeCodes(mapping);
|
||||
}
|
||||
|
@ -131,5 +135,4 @@ public class MetaType extends AbstractType {
|
|||
public boolean isDirty(Object old, Object current, boolean[] checkable, SharedSessionContractImplementor session) throws HibernateException {
|
||||
return checkable[0] && isDirty(old, current, session);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue