re-enable tests
re-organize some tests fixed EnumType mapping from hbm.xml various fixes in HQL, Criteria and parameter handling related to enum values
This commit is contained in:
parent
1114da8b8f
commit
523113d2ca
|
@ -26,11 +26,13 @@ import org.hibernate.resource.beans.spi.ManagedBean;
|
|||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.hibernate.type.spi.TypeConfigurationAware;
|
||||
import org.hibernate.usertype.ParameterizedType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
|
@ -239,6 +241,10 @@ public class TypeDefinition implements Serializable {
|
|||
|
||||
final Object typeInstance = typeBean.getBeanInstance();
|
||||
|
||||
if ( typeInstance instanceof TypeConfigurationAware ) {
|
||||
( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( buildingContext.getBootstrapContext().getTypeConfiguration() );
|
||||
}
|
||||
|
||||
injectParameters( typeInstance, () -> CollectionHelper.asProperties( localTypeParams ) );
|
||||
|
||||
return createResolution(
|
||||
|
|
|
@ -2872,6 +2872,9 @@ public class ModelBinder {
|
|||
|
||||
if ( CollectionHelper.isNotEmpty( typeResolution.parameters ) ) {
|
||||
simpleValue.setTypeParameters( typeResolution.parameters );
|
||||
if ( simpleValue instanceof BasicValue ) {
|
||||
( (BasicValue) simpleValue ).setExplicitTypeParams( typeResolution.parameters );
|
||||
}
|
||||
}
|
||||
|
||||
if ( typeResolution.typeName != null ) {
|
||||
|
@ -2907,6 +2910,7 @@ public class ModelBinder {
|
|||
typeParameters.putAll( typeDefinition.getParameters() );
|
||||
}
|
||||
}
|
||||
|
||||
// parameters on the property mapping should override parameters in the type-def
|
||||
if ( typeSource.getParameters() != null ) {
|
||||
typeParameters.putAll( typeSource.getParameters() );
|
||||
|
|
|
@ -20,6 +20,7 @@ import javax.persistence.Temporal;
|
|||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.CollectionId;
|
||||
|
@ -289,7 +290,7 @@ public class BasicValueBinder<T> implements SqlTypeDescriptorIndicators {
|
|||
else {
|
||||
switch ( kind ) {
|
||||
case ATTRIBUTE: {
|
||||
prepareBasicAttribute( modelXProperty, modelPropertyTypeXClass );
|
||||
prepareBasicAttribute( declaringClassName, modelXProperty, modelPropertyTypeXClass );
|
||||
break;
|
||||
}
|
||||
case COLLECTION_ID: {
|
||||
|
@ -313,6 +314,7 @@ public class BasicValueBinder<T> implements SqlTypeDescriptorIndicators {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void prepareCollectionId(XProperty modelXProperty) {
|
||||
|
@ -439,7 +441,7 @@ public class BasicValueBinder<T> implements SqlTypeDescriptorIndicators {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void prepareBasicAttribute(XProperty attributeDescriptor, XClass attributeType) {
|
||||
private void prepareBasicAttribute(String declaringClassName, XProperty attributeDescriptor, XClass attributeType) {
|
||||
final Class<T> javaType = buildingContext.getBootstrapContext()
|
||||
.getReflectionManager()
|
||||
.toClass( attributeType );
|
||||
|
@ -478,6 +480,16 @@ public class BasicValueBinder<T> implements SqlTypeDescriptorIndicators {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if ( attributeDescriptor.isAnnotationPresent( Enumerated.class ) ) {
|
||||
throw new AnnotationException(
|
||||
String.format(
|
||||
"Attribute [%s.%s] was annotated as enumerated, but its java type is not an enum [%s]",
|
||||
declaringClassName,
|
||||
attributeDescriptor.getName(),
|
||||
attributeType.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
this.enumType = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -531,7 +531,7 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
|
|||
);
|
||||
context.getTypeDefinitionRegistry().register( implicitDefinition );
|
||||
return implicitDefinition.resolve(
|
||||
null,
|
||||
localTypeParams,
|
||||
explicitMutabilityPlanAccess != null
|
||||
? explicitMutabilityPlanAccess.apply( typeConfiguration )
|
||||
: null,
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.metamodel;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
|
@ -17,7 +18,10 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +42,7 @@ public interface MappingMetamodel {
|
|||
/**
|
||||
* todo (6.0) : POC!!! Intended for use in SQM -> SQL translation
|
||||
*/
|
||||
MappingModelExpressable resolveMappingExpressable(SqmExpressable<?> sqmExpressable);
|
||||
MappingModelExpressable resolveMappingExpressable(SqmExpressable<?> sqmExpressable, Function<NavigablePath, TableGroup> tableGroupLocator);
|
||||
|
||||
/**
|
||||
* Given a Java type, determine the corresponding AllowableParameterType to
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.metamodel.EmbeddableType;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
|
@ -61,7 +62,10 @@ import org.hibernate.persister.collection.CollectionPersister;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.persister.spi.PersisterFactory;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -705,7 +709,17 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen
|
|||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable resolveMappingExpressable(SqmExpressable<?> sqmExpressable) {
|
||||
public MappingModelExpressable resolveMappingExpressable(SqmExpressable<?> sqmExpressable, Function<NavigablePath, TableGroup> tableGroupLocator) {
|
||||
if ( sqmExpressable instanceof SqmPath ) {
|
||||
final SqmPath sqmPath = (SqmPath) sqmExpressable;
|
||||
final NavigablePath navigablePath = sqmPath.getNavigablePath();
|
||||
if ( navigablePath.getParent() != null ) {
|
||||
final TableGroup parentTableGroup = tableGroupLocator.apply( navigablePath.getParent() );
|
||||
return parentTableGroup.getModelPart().findSubPart( navigablePath.getLocalName(), null );
|
||||
}
|
||||
return tableGroupLocator.apply( navigablePath.getParent() ).getModelPart();
|
||||
}
|
||||
|
||||
if ( sqmExpressable instanceof BasicType<?> ) {
|
||||
return (BasicType) sqmExpressable;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import javax.persistence.criteria.Subquery;
|
|||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.SortOrder;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectQuery;
|
||||
|
||||
|
@ -258,6 +259,7 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
|
|||
|
||||
@Override
|
||||
<T> JpaExpression<T> literal(T value);
|
||||
<T> SqmExpression<T> literal(T value, SqmExpression<T> typeInferenceSource);
|
||||
|
||||
<T> List<? extends JpaExpression<T>> literals(T[] values);
|
||||
|
||||
|
@ -367,6 +369,8 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
|
|||
|
||||
<T> SqmExpression<T> value(T value);
|
||||
|
||||
<T> SqmExpression<T> value(T value, SqmExpression<T> typeInferenceSource);
|
||||
|
||||
<V, C extends Collection<V>> JpaExpression<Collection<V>> values(C collection);
|
||||
|
||||
@Override
|
||||
|
|
|
@ -232,7 +232,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
|
|||
if ( namedClass.isEnum() ) {
|
||||
return new SqmEnumLiteral(
|
||||
Enum.valueOf( (Class) namedClass, terminal ),
|
||||
(EnumJavaTypeDescriptor<?>) javaTypeDescriptorRegistry.resolveDescriptor( namedClass ),
|
||||
(EnumJavaTypeDescriptor) javaTypeDescriptorRegistry.resolveDescriptor( namedClass ),
|
||||
terminal,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
|
|
|
@ -1730,22 +1730,43 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
private Map<Class<?>, Enum<?>> getPossibleEnumValues(HqlParser.ExpressionContext expressionContext) {
|
||||
ParseTree ctx;
|
||||
// Traverse the expression structure according to the grammar
|
||||
if ( expressionContext instanceof HqlParser.CollateExpressionContext
|
||||
&& expressionContext.getChildCount() == 1
|
||||
&& ( ctx = expressionContext.getChild( 0 ) ) instanceof HqlParser.PrimaryExpressionContext
|
||||
&& ctx.getChildCount() == 1
|
||||
&& ( ctx = expressionContext.getChild( 0 ) ) instanceof HqlParser.PathContext
|
||||
&& ctx.getChildCount() == 1
|
||||
&& ( ctx = ctx.getChild( 0 ) ) instanceof HqlParser.GeneralPathFragmentContext
|
||||
&& ctx.getChildCount() == 1
|
||||
&& ( ctx = ctx.getChild( 0 ) ) instanceof HqlParser.DotIdentifierSequenceContext
|
||||
// With childCount == 1 we could have a simple enum literal e.g. ENUM_VALUE
|
||||
// With childCount == 2 we could have a qualified enum literal e.g. EnumName.ENUM_VALUE
|
||||
&& ( ctx.getChildCount() == 1 || ctx.getChildCount() == 2 && ctx.getChild( 1 ) instanceof HqlParser.DotIdentifierSequenceContinuationContext )
|
||||
&& ctx.getChild( 0 ) instanceof HqlParser.IdentifierContext
|
||||
) {
|
||||
if ( expressionContext instanceof HqlParser.CollateExpressionContext && expressionContext.getChildCount() == 1 ) {
|
||||
ctx = expressionContext.getChild( 0 );
|
||||
|
||||
while ( ctx instanceof HqlParser.PrimaryExpressionContext && ctx.getChildCount() == 1 ) {
|
||||
ctx = ctx.getChild( 0 );
|
||||
}
|
||||
|
||||
if ( ctx instanceof HqlParser.PathContext && ctx.getChildCount() == 1 ) {
|
||||
ctx = ctx.getChild( 0 );
|
||||
|
||||
if ( ctx instanceof HqlParser.GeneralPathFragmentContext && ctx.getChildCount() == 1 ) {
|
||||
ctx = ctx.getChild( 0 );
|
||||
|
||||
if ( ctx instanceof HqlParser.DotIdentifierSequenceContext ) {
|
||||
return creationContext.getJpaMetamodel().getAllowedEnumLiteralTexts().get( ctx.getText() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if ( expressionContext instanceof HqlParser.CollateExpressionContext
|
||||
// && expressionContext.getChildCount() == 1
|
||||
// && ( ctx = expressionContext.getChild( 0 ) ) instanceof HqlParser.PrimaryExpressionContext
|
||||
// && ctx.getChildCount() == 1
|
||||
// && ( ctx = expressionContext.getChild( 0 ) ) instanceof HqlParser.PathContext
|
||||
// && ctx.getChildCount() == 1
|
||||
// && ( ctx = ctx.getChild( 0 ) ) instanceof HqlParser.GeneralPathFragmentContext
|
||||
// && ctx.getChildCount() == 1
|
||||
// && ( ctx = ctx.getChild( 0 ) ) instanceof HqlParser.DotIdentifierSequenceContext
|
||||
// // With childCount == 1 we could have a simple enum literal e.g. ENUM_VALUE
|
||||
// // With childCount == 2 we could have a qualified enum literal e.g. EnumName.ENUM_VALUE
|
||||
// && ( ctx.getChildCount() == 1 || ctx.getChildCount() == 2 && ctx.getChild( 1 ) instanceof HqlParser.DotIdentifierSequenceContinuationContext )
|
||||
// && ctx.getChild( 0 ) instanceof HqlParser.IdentifierContext
|
||||
// ) {
|
||||
// return creationContext.getJpaMetamodel().getAllowedEnumLiteralTexts().get( ctx.getText() );
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.function;
|
||||
|
||||
import org.hibernate.metamodel.MappingMetamodel;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
|
@ -116,12 +117,11 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
mapping = returnTypeResolver.resolveFunctionReturnType(
|
||||
() -> {
|
||||
try {
|
||||
// I think it's supposed to be this, but
|
||||
// resolveMappingExpressable() looks to
|
||||
// be unfinished, and throws
|
||||
return (BasicValuedMapping)
|
||||
walker.getCreationContext().getDomainModel()
|
||||
.resolveMappingExpressable( getNodeType() );
|
||||
final MappingMetamodel domainModel = walker.getCreationContext().getDomainModel();
|
||||
return (BasicValuedMapping) domainModel.resolveMappingExpressable(
|
||||
getNodeType(),
|
||||
walker.getFromClauseAccess()::getTableGroup
|
||||
);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null; // this works at least approximately
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.sql.Time;
|
|||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -55,15 +54,13 @@ import org.hibernate.query.criteria.JpaCoalesce;
|
|||
import org.hibernate.query.criteria.JpaCompoundSelection;
|
||||
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.criteria.JpaQueryGroup;
|
||||
import org.hibernate.query.criteria.JpaQueryPart;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.criteria.LiteralHandlingMode;
|
||||
import org.hibernate.query.criteria.ValueHandlingMode;
|
||||
import org.hibernate.query.internal.QueryHelper;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||
|
@ -119,6 +116,7 @@ import org.hibernate.service.ServiceRegistry;
|
|||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType;
|
||||
|
@ -618,18 +616,33 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <N extends Number> SqmExpression<N> sum(Expression<? extends N> x, N y) {
|
||||
return createSqmArithmeticNode( BinaryArithmeticOperator.ADD, (SqmExpression<?>) x, value( y ) );
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.ADD,
|
||||
(SqmExpression<?>) x,
|
||||
value( y, (SqmExpression) x )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <N extends Number> SqmExpression<N> sum(N x, Expression<? extends N> y) {
|
||||
return createSqmArithmeticNode( BinaryArithmeticOperator.ADD, value( x ), (SqmExpression<?>) y );
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.ADD,
|
||||
value( x, (SqmExpression) y ),
|
||||
(SqmExpression<?>) y
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <N extends Number> SqmExpression<N> prod(Expression<? extends N> x, Expression<? extends N> y) {
|
||||
return createSqmArithmeticNode( BinaryArithmeticOperator.ADD, value( x ), (SqmExpression<?>) y );
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.ADD,
|
||||
value( x, (SqmExpression) y ),
|
||||
(SqmExpression<?>) y
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -652,20 +665,22 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <N extends Number> SqmExpression<N> diff(Expression<? extends N> x, N y) {
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.SUBTRACT,
|
||||
(SqmExpression<?>) x,
|
||||
value( y )
|
||||
(SqmExpression) x,
|
||||
value( y, (SqmExpression) x )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <N extends Number> SqmExpression<N> diff(N x, Expression<? extends N> y) {
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.SUBTRACT,
|
||||
value( x ),
|
||||
(SqmExpression<?>) y
|
||||
value( x, (SqmExpression) y ),
|
||||
(SqmExpression) y
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -679,20 +694,22 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmExpression<Number> quot(Expression<? extends Number> x, Number y) {
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.QUOT,
|
||||
(SqmExpression<?>) x,
|
||||
value( y )
|
||||
(SqmExpression) x,
|
||||
value( y, (SqmExpression) x )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmExpression<Number> quot(Number x, Expression<? extends Number> y) {
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.QUOT,
|
||||
value( x ),
|
||||
(SqmExpression<?>) y
|
||||
value( x, (SqmExpression) y ),
|
||||
(SqmExpression) y
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -706,20 +723,22 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmExpression<Integer> mod(Expression<Integer> x, Integer y) {
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.MODULO,
|
||||
(SqmExpression<?>) x,
|
||||
value( y )
|
||||
(SqmExpression) x,
|
||||
value( y, (SqmExpression) x )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmExpression<Integer> mod(Integer x, Expression<Integer> y) {
|
||||
return createSqmArithmeticNode(
|
||||
BinaryArithmeticOperator.MODULO,
|
||||
value( x ),
|
||||
(SqmExpression<?>) y
|
||||
value( x, (SqmExpression) y ),
|
||||
(SqmExpression) y
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -774,11 +793,36 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SqmExpression<String> toString(Expression<Character> character) {
|
||||
return ( (SqmExpression<?>) character ).asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SqmLiteral<T> literal(T value, SqmExpression<T> typeInferenceSource) {
|
||||
if ( value == null ) {
|
||||
return new SqmLiteralNull<>( this );
|
||||
}
|
||||
|
||||
final SqmExpressable<T> expressable = resolveInferredType( value, typeInferenceSource, getTypeConfiguration() );
|
||||
return new SqmLiteral<>( value, expressable, this );
|
||||
}
|
||||
|
||||
private static <T> SqmExpressable<T> resolveInferredType(
|
||||
T value,
|
||||
SqmExpression<T> typeInferenceSource,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
if ( typeInferenceSource != null ) {
|
||||
return typeInferenceSource.getNodeType();
|
||||
}
|
||||
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (BasicType<T>) typeConfiguration.getBasicTypeForJavaType( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SqmLiteral<T> literal(T value) {
|
||||
if ( value == null ) {
|
||||
|
@ -927,10 +971,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public SqmExpression<String> concat(Expression<String> x, String y) {
|
||||
final SqmExpression xSqmExpression = (SqmExpression) x;
|
||||
final SqmExpression ySqmExpression = value( y );
|
||||
//noinspection unchecked
|
||||
final SqmExpression ySqmExpression = value( y, xSqmExpression );
|
||||
|
||||
return getFunctionDescriptor( "concat" ).generateSqmExpression(
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
(AllowableFunctionReturnType<String>) highestPrecedenceType(
|
||||
|
@ -944,10 +989,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public SqmExpression<String> concat(String x, Expression<String> y) {
|
||||
final SqmExpression xSqmExpression = value( x );
|
||||
final SqmExpression ySqmExpression = (SqmExpression) y;
|
||||
//noinspection unchecked
|
||||
final SqmExpression xSqmExpression = value( x, ySqmExpression );
|
||||
|
||||
return getFunctionDescriptor( "concat" ).generateSqmExpression(
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
(AllowableFunctionReturnType<String>) highestPrecedenceType(
|
||||
|
@ -961,10 +1007,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public SqmExpression<String> concat(String x, String y) {
|
||||
final SqmExpression xSqmExpression = value( x );
|
||||
final SqmExpression ySqmExpression = value( y );
|
||||
//noinspection unchecked
|
||||
final SqmExpression ySqmExpression = value( y, xSqmExpression );
|
||||
|
||||
return getFunctionDescriptor( "concat" ).generateSqmExpression(
|
||||
asList( xSqmExpression, ySqmExpression ),
|
||||
(AllowableFunctionReturnType<String>) highestPrecedenceType(
|
||||
|
@ -1327,6 +1374,49 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an expression for the value with the given "type inference" information
|
||||
*/
|
||||
@Override
|
||||
public <T> SqmExpression<T> value(T value, SqmExpression<T> typeInferenceSource) {
|
||||
if ( typeInferenceSource == null ) {
|
||||
return value( value );
|
||||
}
|
||||
|
||||
if ( criteriaValueHandlingMode == ValueHandlingMode.INLINE ) {
|
||||
return literal( value, typeInferenceSource );
|
||||
}
|
||||
|
||||
return new JpaCriteriaParameter<>(
|
||||
resolveInferredParameterType( value, typeInferenceSource, getTypeConfiguration() ),
|
||||
value,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
private static <T> AllowableParameterType<T> resolveInferredParameterType(
|
||||
T value,
|
||||
SqmExpression<T> typeInferenceSource,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
if ( typeInferenceSource != null ) {
|
||||
if ( typeInferenceSource instanceof AllowableParameterType ) {
|
||||
//noinspection unchecked
|
||||
return (AllowableParameterType<T>) typeInferenceSource;
|
||||
}
|
||||
|
||||
if ( typeInferenceSource.getNodeType() instanceof AllowableParameterType ) {
|
||||
return (AllowableParameterType<T>) typeInferenceSource.getNodeType();
|
||||
}
|
||||
}
|
||||
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (BasicType<T>) typeConfiguration.getBasicTypeForJavaType( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SqmExpression<T> value(T value) {
|
||||
if ( criteriaValueHandlingMode == ValueHandlingMode.INLINE ) {
|
||||
|
@ -1394,7 +1484,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
|
||||
@Override
|
||||
public <Y> JpaCoalesce<Y> coalesce(Expression<? extends Y> x, Y y) {
|
||||
return coalesce( x, value( y ) );
|
||||
return coalesce( x, value( y, (SqmExpression) x ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1406,7 +1496,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
@Override
|
||||
public <Y> SqmExpression<Y> nullif(Expression<Y> x, Y y) {
|
||||
//noinspection unchecked
|
||||
return createNullifFunctionNode( (SqmExpression) x, value( y ) );
|
||||
return createNullifFunctionNode( (SqmExpression) x, value( y, (SqmExpression) x ) );
|
||||
}
|
||||
|
||||
private <Y> SqmExpression<Y> createNullifFunctionNode(SqmExpression<Y> first, SqmExpression<Y> second) {
|
||||
|
@ -1563,11 +1653,13 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate between(Expression<? extends Y> value, Y lower, Y upper) {
|
||||
final SqmExpression valueExpression = (SqmExpression) value;
|
||||
return new SqmBetweenPredicate(
|
||||
(SqmExpression) value,
|
||||
value( lower ),
|
||||
value( upper ),
|
||||
valueExpression,
|
||||
value( lower, valueExpression ),
|
||||
value( upper, valueExpression ),
|
||||
false,
|
||||
this
|
||||
);
|
||||
|
@ -1584,11 +1676,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmPredicate equal(Expression<?> x, Object y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.EQUAL,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1604,11 +1697,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public SqmPredicate notEqual(Expression<?> x, Object y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
(SqmExpression) x,
|
||||
ComparisonOperator.NOT_EQUAL,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1624,11 +1718,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Y y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1644,11 +1739,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThanOrEqualTo(Expression<? extends Y> x, Y y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1664,11 +1760,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate lessThan(Expression<? extends Y> x, Y y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1688,7 +1785,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
value( y ),
|
||||
(SqmExpression<?>) y,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1704,11 +1801,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmPredicate gt(Expression<? extends Number> x, Number y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1724,11 +1822,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmPredicate ge(Expression<? extends Number> x, Number y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1744,11 +1843,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmPredicate lt(Expression<? extends Number> x, Number y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1764,11 +1864,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SqmPredicate le(Expression<? extends Number> x, Number y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
value( y ),
|
||||
value( y, (SqmExpression) x ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1816,7 +1917,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
public SqmPredicate like(Expression<String> searchString, String pattern) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
value( pattern ),
|
||||
value( pattern, (SqmExpression) searchString ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -1845,7 +1946,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
public SqmPredicate like(Expression<String> searchString, String pattern, Expression<Character> escapeChar) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
value( pattern ),
|
||||
value( pattern, (SqmExpression) searchString ),
|
||||
(SqmExpression) escapeChar,
|
||||
this
|
||||
);
|
||||
|
@ -1855,7 +1956,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext {
|
|||
public SqmPredicate like(Expression<String> searchString, String pattern, char escapeChar) {
|
||||
return new SqmLikePredicate(
|
||||
(SqmExpression) searchString,
|
||||
value( pattern ),
|
||||
value( pattern, (SqmExpression) searchString ),
|
||||
literal( escapeChar ),
|
||||
this
|
||||
);
|
||||
|
|
|
@ -213,6 +213,7 @@ public class SqmUtil {
|
|||
parameterType,
|
||||
jdbcParams,
|
||||
valueItr.next(),
|
||||
tableGroupLocator,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
@ -232,6 +233,7 @@ public class SqmUtil {
|
|||
parameterType,
|
||||
expansionJdbcParams,
|
||||
valueItr.next(),
|
||||
tableGroupLocator,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
@ -292,6 +294,7 @@ public class SqmUtil {
|
|||
parameterType,
|
||||
jdbcParams,
|
||||
bindValue,
|
||||
tableGroupLocator,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
@ -308,6 +311,7 @@ public class SqmUtil {
|
|||
AllowableParameterType<?> parameterType,
|
||||
List<JdbcParameter> jdbcParams,
|
||||
Object bindValue,
|
||||
Function<NavigablePath, TableGroup> tableGroupLocator,
|
||||
SharedSessionContractImplementor session) {
|
||||
final MappingMetamodel domainModel = session.getFactory().getDomainModel();
|
||||
final MappingModelExpressable mappingExpressable;
|
||||
|
@ -335,7 +339,7 @@ public class SqmUtil {
|
|||
}
|
||||
}
|
||||
else {
|
||||
mappingExpressable = domainModel.resolveMappingExpressable( parameterType );
|
||||
mappingExpressable = domainModel.resolveMappingExpressable( parameterType, tableGroupLocator );
|
||||
}
|
||||
|
||||
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
|
||||
|
|
|
@ -1268,6 +1268,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
);
|
||||
}
|
||||
|
||||
private TableGroup findTableGroupByPath(NavigablePath navigablePath) {
|
||||
return getFromClauseAccess().getTableGroup( navigablePath );
|
||||
}
|
||||
|
||||
private interface OrderByFragmentConsumer {
|
||||
void accept(OrderByFragment orderByFragment, TableGroup tableGroup);
|
||||
|
||||
|
@ -2170,7 +2174,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
protected MappingModelExpressable<?> resolveMappingExpressable(SqmExpressable<?> nodeType) {
|
||||
final MappingModelExpressable valueMapping = getCreationContext().getDomainModel().resolveMappingExpressable(
|
||||
nodeType );
|
||||
nodeType,
|
||||
this::findTableGroupByPath
|
||||
);
|
||||
|
||||
if ( valueMapping == null ) {
|
||||
final Supplier<MappingModelExpressable> currentExpressableSupplier = inferrableTypeAccessStack.getCurrent();
|
||||
|
@ -2224,7 +2230,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
sqmExpressable = selectionNodeType;
|
||||
}
|
||||
|
||||
final MappingModelExpressable<?> expressable = domainModel.resolveMappingExpressable( sqmExpressable );
|
||||
final MappingModelExpressable<?> expressable = domainModel.resolveMappingExpressable( sqmExpressable, this::findTableGroupByPath );
|
||||
|
||||
if ( expressable != null ) {
|
||||
return expressable;
|
||||
|
@ -2243,7 +2249,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
log.debugf( "Determining mapping-model type for generalized SqmExpression : %s", sqmExpression );
|
||||
final SqmExpressable<?> nodeType = sqmExpression.getNodeType();
|
||||
final MappingModelExpressable valueMapping = domainModel.resolveMappingExpressable(
|
||||
nodeType );
|
||||
nodeType,
|
||||
this::findTableGroupByPath
|
||||
);
|
||||
|
||||
if ( valueMapping == null ) {
|
||||
final Supplier<MappingModelExpressable> currentExpressableSupplier = inferrableTypeAccessStack.getCurrent();
|
||||
|
@ -2289,6 +2297,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
assert parameterSqmType != null;
|
||||
|
||||
if ( parameterSqmType instanceof SqmPath ) {
|
||||
final SqmPath sqmPath = (SqmPath) parameterSqmType;
|
||||
final NavigablePath navigablePath = sqmPath.getNavigablePath();
|
||||
if ( navigablePath.getParent() != null ) {
|
||||
final TableGroup tableGroup = getFromClauseAccess().getTableGroup( navigablePath.getParent() );
|
||||
return tableGroup.getModelPart().findSubPart(
|
||||
navigablePath.getLocalName(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
return getFromClauseAccess().getTableGroup( navigablePath ).getModelPart();
|
||||
}
|
||||
|
||||
if ( parameterSqmType instanceof BasicValuedMapping ) {
|
||||
return (BasicValuedMapping) parameterSqmType;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.domain;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.PathException;
|
||||
|
@ -16,11 +17,14 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmBasicValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
||||
public class SqmBasicValuedSimplePath<T>
|
||||
extends AbstractSqmSimplePath<T>
|
||||
implements AllowableParameterType<T> {
|
||||
public SqmBasicValuedSimplePath(
|
||||
NavigablePath navigablePath,
|
||||
SqmPathSource<T> referencedPathSource,
|
||||
|
@ -78,6 +82,21 @@ public class SqmBasicValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
throw new UnsupportedOperationException( "Basic-value cannot be treated (downcast)" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<T> getExpressableJavaTypeDescriptor() {
|
||||
return getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.BASIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getJavaType() {
|
||||
return getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Visitation
|
||||
|
|
|
@ -116,7 +116,7 @@ public class SqmCaseSearched<R>
|
|||
|
||||
@Override
|
||||
public SqmCaseSearched<R> when(Expression<Boolean> condition, R result) {
|
||||
when( nodeBuilder().wrap( condition ), nodeBuilder().value( result ) );
|
||||
when( nodeBuilder().wrap( condition ), nodeBuilder().value( result, otherwise ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ public class SqmCaseSimple<T,R>
|
|||
@Override
|
||||
public JpaSimpleCase<T, R> when(T condition, Expression<? extends R> result) {
|
||||
//noinspection unchecked
|
||||
when( nodeBuilder().value( condition ), (SqmExpression) result );
|
||||
when( nodeBuilder().value( condition, (SqmExpression<T>) result ), (SqmExpression<R>) result );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ public class SqmCaseSimple<T,R>
|
|||
@Override
|
||||
public JpaSimpleCase<T, R> otherwise(Expression<? extends R> result) {
|
||||
//noinspection unchecked
|
||||
otherwise( (SqmExpression) result );
|
||||
otherwise( (SqmExpression<R>) result );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.query.criteria.JpaCoalesce;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
|
@ -69,14 +70,23 @@ public class SqmCoalesce<T> extends AbstractSqmExpression<T> implements JpaCoale
|
|||
|
||||
@Override
|
||||
public SqmCoalesce<T> value(T value) {
|
||||
value( nodeBuilder().value( value ) );
|
||||
value( nodeBuilder().value( value, firstOrNull() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
private SqmExpression<T> firstOrNull() {
|
||||
if ( CollectionHelper.isEmpty( arguments ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<T>) arguments.get( 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCoalesce<T> value(Expression<? extends T> value) {
|
||||
//noinspection unchecked
|
||||
value( (SqmExpression) value );
|
||||
value( (SqmExpression<? extends T>) value );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -90,8 +100,9 @@ public class SqmCoalesce<T> extends AbstractSqmExpression<T> implements JpaCoale
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SqmCoalesce<T> values(T... values) {
|
||||
final SqmExpression<T> firstOrNull = firstOrNull();
|
||||
for ( T value : values ) {
|
||||
value( nodeBuilder().value( value ) );
|
||||
value( nodeBuilder().value( value, firstOrNull ) );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -73,18 +73,22 @@ public class SqmInListPredicate<T> extends AbstractNegatableSqmPredicate impleme
|
|||
@Override
|
||||
public SqmInPredicate<T> value(Object value) {
|
||||
if ( value instanceof Collection ) {
|
||||
( (Collection) value ).forEach(
|
||||
v -> addExpression( nodeBuilder().value( v ) )
|
||||
//noinspection unchecked
|
||||
( (Collection<T>) value ).forEach(
|
||||
v -> addExpression( nodeBuilder().value( v, testExpression ) )
|
||||
);
|
||||
return this;
|
||||
}
|
||||
addExpression( nodeBuilder().value( value ) );
|
||||
else {
|
||||
//noinspection unchecked
|
||||
addExpression( nodeBuilder().value( (T) value, testExpression ) );
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmInPredicate<T> value(Expression value) {
|
||||
addExpression( (SqmExpression) value );
|
||||
addExpression( (SqmExpression<T>) value );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -98,11 +102,11 @@ public class SqmInListPredicate<T> extends AbstractNegatableSqmPredicate impleme
|
|||
return listExpressions;
|
||||
}
|
||||
|
||||
public void addExpression(SqmExpression expression) {
|
||||
public <X> void addExpression(SqmExpression<X> expression) {
|
||||
implyListElementType( expression );
|
||||
|
||||
//noinspection unchecked
|
||||
listExpressions.add( expression );
|
||||
listExpressions.add( (SqmExpression<T>) expression );
|
||||
}
|
||||
|
||||
private void implyListElementType(SqmExpression expression) {
|
||||
|
|
|
@ -36,6 +36,13 @@ import org.hibernate.usertype.UserVersionType;
|
|||
* Adapts {@link UserType} to the generic {@link Type} interface, in order
|
||||
* to isolate user code from changes in the internal Type contracts.
|
||||
*
|
||||
* @apiNote Many of the interfaces implemented here are implemented just to
|
||||
* handle the case of the wrapped type implementing them so we can pass them
|
||||
* along.
|
||||
*
|
||||
* todo (6.0) : ^^ this introduces a problem in code that relies on `instance of` checks
|
||||
* against any of these interfaces when the wrapped type does not
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
|
|
@ -44,18 +44,22 @@ import org.jboss.logging.Logger;
|
|||
/**
|
||||
* Value type mapper for enumerations.
|
||||
*
|
||||
* Generally speaking, the proper configuration is picked up from the annotations associated with the mapped attribute.
|
||||
* Provides 2 distinct forms of "configuration" - one for hbm.xml mapping and
|
||||
* another for annotation/orm.xml mapping triggered within the {@link #setParameterValues}
|
||||
* method
|
||||
*
|
||||
* There are a few configuration parameters understood by this type mapper:<ul>
|
||||
* Annotation based config relies on a {@link ParameterType} reference passed as
|
||||
* an entry in the parameter values under the key {@link #PARAMETER_TYPE}
|
||||
*
|
||||
* hbm.xml based config relies on a number of values from the parameters: <ul>
|
||||
* <li>
|
||||
* <strong>enumClass</strong> - Names the enumeration class.
|
||||
* {@link #ENUM} - Name the enumeration class.
|
||||
* </li>
|
||||
* <li>
|
||||
* <strong>useNamed</strong> - Should enum be mapped via name. Default is to map as ordinal. Used when
|
||||
* annotations are not used (otherwise {@link javax.persistence.EnumType} is used).
|
||||
* {@link #NAMED} - Should enum be mapped via name. Default is to map as ordinal.
|
||||
* </li>
|
||||
* <li>
|
||||
* <strong>type</strong> - Identifies the JDBC type (via type code) to be used for the column.
|
||||
* {@link #TYPE} - JDBC type code (legacy alternative to {@link #NAMED})
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
|
@ -103,6 +107,8 @@ public class EnumType<T extends Enum<T>>
|
|||
// 2) we are not passed a ParameterType - generally this indicates a hbm.xml binding case.
|
||||
final ParameterType reader = (ParameterType) parameters.get( PARAMETER_TYPE );
|
||||
|
||||
// the `reader != null` block handles annotations, while the `else` block
|
||||
// handles hbm.xml
|
||||
if ( reader != null ) {
|
||||
enumClass = reader.getReturnedClass().asSubclass( Enum.class );
|
||||
|
||||
|
@ -183,20 +189,23 @@ public class EnumType<T extends Enum<T>>
|
|||
}
|
||||
|
||||
private javax.persistence.EnumType getEnumType(ParameterType reader) {
|
||||
javax.persistence.EnumType enumType = null;
|
||||
if ( reader == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( reader.isPrimaryKey() ) {
|
||||
MapKeyEnumerated enumAnn = getAnnotation( reader.getAnnotationsMethod(), MapKeyEnumerated.class );
|
||||
final MapKeyEnumerated enumAnn = getAnnotation( reader.getAnnotationsMethod(), MapKeyEnumerated.class );
|
||||
if ( enumAnn != null ) {
|
||||
enumType = enumAnn.value();
|
||||
return enumAnn.value();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Enumerated enumAnn = getAnnotation( reader.getAnnotationsMethod(), Enumerated.class );
|
||||
|
||||
final Enumerated enumAnn = getAnnotation( reader.getAnnotationsMethod(), Enumerated.class );
|
||||
if ( enumAnn != null ) {
|
||||
enumType = enumAnn.value();
|
||||
return enumAnn.value();
|
||||
}
|
||||
}
|
||||
return enumType;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private <A extends Annotation> A getAnnotation(Annotation[] annotations, Class<A> anClass) {
|
||||
|
@ -209,17 +218,24 @@ public class EnumType<T extends Enum<T>>
|
|||
}
|
||||
|
||||
private EnumValueConverter<T,?> interpretParameters(Properties parameters) {
|
||||
final EnumJavaTypeDescriptor<?> enumJavaDescriptor = (EnumJavaTypeDescriptor<?>) typeConfiguration
|
||||
//noinspection rawtypes
|
||||
final EnumJavaTypeDescriptor enumJavaDescriptor = (EnumJavaTypeDescriptor) typeConfiguration
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( enumClass );
|
||||
|
||||
final ParameterType reader = (ParameterType) parameters.get( PARAMETER_TYPE );
|
||||
final javax.persistence.EnumType enumType = getEnumType( reader );
|
||||
// this method should only be called for hbm.xml handling
|
||||
assert parameters.get( PARAMETER_TYPE ) == null;
|
||||
|
||||
final LocalSqlTypeDescriptorIndicators localIndicators = new LocalSqlTypeDescriptorIndicators(
|
||||
enumType,
|
||||
reader.getColumnLengths()[0],
|
||||
reader
|
||||
// use ORDINAL as default for hbm.xml mappings
|
||||
javax.persistence.EnumType.ORDINAL,
|
||||
// Is there a reasonable value here? Limits the
|
||||
// number of enums that can be stored:
|
||||
// 1 = 10
|
||||
// 2 = 100
|
||||
// etc
|
||||
-1L,
|
||||
null
|
||||
);
|
||||
final BasicJavaDescriptor<?> stringJavaDescriptor = (BasicJavaDescriptor<?>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||
final BasicJavaDescriptor<?> integerJavaDescriptor = (BasicJavaDescriptor<?>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Integer.class );
|
||||
|
@ -450,11 +466,13 @@ public class EnumType<T extends Enum<T>>
|
|||
return true;
|
||||
}
|
||||
|
||||
if ( reader != null ) {
|
||||
for ( Annotation annotation : reader.getAnnotationsMethod() ) {
|
||||
if ( annotation instanceof Nationalized ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.orm.test.mapping.converted.enums;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@DomainModel(
|
||||
xmlMappings = "/org/hibernate/orm/test/mapping/converted/enums/Person.hbm.xml"
|
||||
)
|
||||
@SessionFactory
|
||||
public class EnumExplicitTypeTest {
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-10766")
|
||||
public void hbmEnumWithExplicitTypeTest(SessionFactoryScope scope) {
|
||||
final Long id = scope.fromTransaction(
|
||||
(session) -> {
|
||||
Person person = Person.person( Gender.MALE, HairColor.BROWN );
|
||||
person.setOriginalHairColor( HairColor.BLONDE );
|
||||
session.persist( person );
|
||||
|
||||
return person.getId();
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
Number personId = (Number) session.createNativeQuery(
|
||||
"select id from Person where originalHairColor = :color")
|
||||
.setParameter("color", HairColor.BLONDE.name())
|
||||
.getSingleResult();
|
||||
|
||||
assertEquals( (long) id, personId.longValue() );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
|
@ -51,8 +51,13 @@ public class EnumTypeTest extends BaseCoreFunctionalTestCase {
|
|||
|
||||
private Triggerable extractorTriggerable;
|
||||
|
||||
@Override
|
||||
protected String getBaseForMappings() {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected String[] getMappings() {
|
||||
return new String[] { "enums/Person.hbm.xml" };
|
||||
return new String[] { "org/hibernate/orm/test/mapping/converted/enums/Person.hbm.xml" };
|
||||
}
|
||||
|
||||
@Override
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
/**
|
||||
* @author Brett Meyer
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
/**
|
||||
* @author Brett Meyer
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Enumerated;
|
||||
|
@ -12,22 +12,21 @@ import javax.persistence.Id;
|
|||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistry;
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class InvalidEnumeratedJavaTypeTest extends BaseUnitTestCase {
|
||||
@ServiceRegistry
|
||||
public class InvalidEnumeratedJavaTypeTest {
|
||||
@Test
|
||||
public void testInvalidMapping() {
|
||||
MetadataSources metadataSources = new MetadataSources( )
|
||||
public void testInvalidMapping(ServiceRegistryScope scope) {
|
||||
MetadataSources metadataSources = new MetadataSources( scope.getRegistry() )
|
||||
.addAnnotatedClass( TheEntity.class );
|
||||
try {
|
||||
metadataSources.buildMetadata();
|
||||
|
@ -35,12 +34,6 @@ public class InvalidEnumeratedJavaTypeTest extends BaseUnitTestCase {
|
|||
}
|
||||
catch (AnnotationException ignore) {
|
||||
}
|
||||
finally {
|
||||
ServiceRegistry metaServiceRegistry = metadataSources.getServiceRegistry();
|
||||
if(metaServiceRegistry instanceof BootstrapServiceRegistry ) {
|
||||
BootstrapServiceRegistryBuilder.destroy( metaServiceRegistry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
public class Person {
|
||||
private long id;
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.orm.test.mapping.converted.enums;
|
||||
|
||||
import org.hibernate.internal.util.SerializationHelper;
|
||||
import org.hibernate.metamodel.model.convert.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.IntegerTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.hibernate.testing.orm.junit.BaseUnitTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@BaseUnitTest
|
||||
public class TestEnumTypeSerialization {
|
||||
@Test
|
||||
public void testOrdinalSerializability() {
|
||||
TypeConfiguration typeConfiguration = new TypeConfiguration();
|
||||
final EnumJavaTypeDescriptor<UnspecifiedEnumTypeEntity.E1> enumJtd = (EnumJavaTypeDescriptor) typeConfiguration
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.resolveDescriptor( UnspecifiedEnumTypeEntity.E1.class );
|
||||
|
||||
final OrdinalEnumValueConverter valueConverter = new OrdinalEnumValueConverter(
|
||||
enumJtd,
|
||||
IntegerTypeDescriptor.INSTANCE,
|
||||
org.hibernate.type.descriptor.java.IntegerTypeDescriptor.INSTANCE
|
||||
);
|
||||
|
||||
final EnumType<UnspecifiedEnumTypeEntity.E1> enumType = new EnumType<>(
|
||||
UnspecifiedEnumTypeEntity.E1.class,
|
||||
valueConverter,
|
||||
typeConfiguration
|
||||
);
|
||||
|
||||
SerializationHelper.clone( enumType );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedSerializability() {
|
||||
TypeConfiguration typeConfiguration = new TypeConfiguration();
|
||||
final EnumJavaTypeDescriptor<UnspecifiedEnumTypeEntity.E1> enumJtd = (EnumJavaTypeDescriptor) typeConfiguration
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.resolveDescriptor( UnspecifiedEnumTypeEntity.E1.class );
|
||||
|
||||
final NamedEnumValueConverter valueConverter = new NamedEnumValueConverter(
|
||||
enumJtd,
|
||||
VarcharTypeDescriptor.INSTANCE,
|
||||
StringTypeDescriptor.INSTANCE
|
||||
);
|
||||
|
||||
final EnumType<UnspecifiedEnumTypeEntity.E1> enumType = new EnumType<>(
|
||||
UnspecifiedEnumTypeEntity.E1.class,
|
||||
valueConverter,
|
||||
typeConfiguration
|
||||
);
|
||||
|
||||
SerializationHelper.clone( enumType );
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
* 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.test.enums;
|
||||
package org.hibernate.orm.test.mapping.converted.enums;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
@ -28,9 +28,14 @@ import org.junit.Test;
|
|||
@TestForIssue( jiraKey = "HHH-7780" )
|
||||
@RequiresDialect( value = H2Dialect.class )
|
||||
public class UnspecifiedEnumTypeTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected String getBaseForMappings() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getMappings() {
|
||||
return new String[] { "enums/mappings.hbm.xml" };
|
||||
return new String[] { "org/hibernate/orm/test/mapping/converted/enums/mappings.hbm.xml" };
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* 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.test.enums;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class EnumExplicitTypeTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
protected String[] getMappings() {
|
||||
return new String[] { "enums/Person.hbm.xml" };
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-10766")
|
||||
public void hbmEnumWithExplicitTypeTest() {
|
||||
long id = doInHibernate( this::sessionFactory, session -> {
|
||||
Person person = Person.person(Gender.MALE, HairColor.BROWN);
|
||||
person.setOriginalHairColor(HairColor.BLONDE);
|
||||
session.persist(person);
|
||||
|
||||
return person.getId();
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Number personId = (Number) session.createNativeQuery(
|
||||
"select id from Person where originalHairColor = :color")
|
||||
.setParameter("color", HairColor.BLONDE.name())
|
||||
.getSingleResult();
|
||||
|
||||
assertEquals( id, personId.longValue() );
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* 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.test.enums;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.internal.util.SerializationHelper;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TestEnumTypeSerialization extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testSerializability() {
|
||||
TypeConfiguration typeConfiguration = new TypeConfiguration();
|
||||
{
|
||||
// test ordinal mapping
|
||||
EnumType enumType = new EnumType( );
|
||||
enumType.setTypeConfiguration( typeConfiguration );
|
||||
Properties properties = new Properties();
|
||||
properties.put( EnumType.ENUM, UnspecifiedEnumTypeEntity.E1.class.getName() );
|
||||
enumType.setParameterValues( properties );
|
||||
assertTrue( enumType.isOrdinal() );
|
||||
SerializationHelper.clone( enumType );
|
||||
}
|
||||
|
||||
{
|
||||
// test named mapping
|
||||
EnumType enumType = new EnumType();
|
||||
enumType.setTypeConfiguration( typeConfiguration );
|
||||
Properties properties = new Properties();
|
||||
properties.put( EnumType.ENUM, UnspecifiedEnumTypeEntity.E1.class.getName() );
|
||||
properties.put( EnumType.NAMED, "true" );
|
||||
enumType.setParameterValues( properties );
|
||||
assertFalse( enumType.isOrdinal() );
|
||||
SerializationHelper.clone( enumType );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,27 +10,27 @@
|
|||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="org.hibernate.test.enums.Person">
|
||||
<class name="org.hibernate.orm.test.mapping.converted.enums.Person">
|
||||
<id name="id" type="long">
|
||||
<generator class="native"></generator>
|
||||
</id>
|
||||
|
||||
<property name="gender" not-null="true">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<param name="enumClass">org.hibernate.test.enums.Gender</param>
|
||||
<param name="enumClass">org.hibernate.orm.test.mapping.converted.enums.Gender</param>
|
||||
<param name="type">12</param>
|
||||
</type>
|
||||
</property>
|
||||
|
||||
<property name="hairColor" not-null="true">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<param name="enumClass">org.hibernate.test.enums.HairColor</param>
|
||||
<param name="enumClass">org.hibernate.orm.test.mapping.converted.enums.HairColor</param>
|
||||
</type>
|
||||
</property>
|
||||
|
||||
<property name="originalHairColor">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<param name="enumClass">org.hibernate.test.enums.HairColor</param>
|
||||
<param name="enumClass">org.hibernate.orm.test.mapping.converted.enums.HairColor</param>
|
||||
<param name="type">12</param>
|
||||
</type>
|
||||
</property>
|
|
@ -7,20 +7,20 @@
|
|||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
<hibernate-mapping>
|
||||
<class name="org.hibernate.test.enums.UnspecifiedEnumTypeEntity" table="ENUM_ENTITY">
|
||||
<class name="org.hibernate.orm.test.mapping.converted.enums.UnspecifiedEnumTypeEntity" table="ENUM_ENTITY">
|
||||
<id name="id" column="ID" type="long">
|
||||
<generator class="increment" />
|
||||
</id>
|
||||
<property name="enum1">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<!--<param name="useNamed">true</param>-->
|
||||
<param name="enumClass">org.hibernate.test.enums.UnspecifiedEnumTypeEntity$E1</param>
|
||||
<param name="enumClass">org.hibernate.orm.test.mapping.converted.enums.UnspecifiedEnumTypeEntity$E1</param>
|
||||
</type>
|
||||
</property>
|
||||
<property name="enum2">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<!--<param name="useNamed">false</param>-->
|
||||
<param name="enumClass">org.hibernate.test.enums.UnspecifiedEnumTypeEntity$E2</param>
|
||||
<param name="enumClass">org.hibernate.orm.test.mapping.converted.enums.UnspecifiedEnumTypeEntity$E2</param>
|
||||
</type>
|
||||
</property>
|
||||
</class>
|
|
@ -35,6 +35,8 @@ dependencies {
|
|||
testRuntime( libraries.log4j )
|
||||
}
|
||||
|
||||
tasks.test.include '**/*'
|
||||
|
||||
// todo : Fold into hibernate-core and publish in separate publications
|
||||
// once http://issues.gradle.org/browse/GRADLE-2966 is resolved;
|
||||
// that will allow us to keep the same artifactId and publish the pom
|
||||
|
|
Loading…
Reference in New Issue