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:
Steve Ebersole 2021-03-24 15:33:30 -05:00
parent 1114da8b8f
commit 523113d2ca
35 changed files with 611 additions and 331 deletions

View File

@ -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(

View File

@ -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() );

View File

@ -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;
}

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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()
);

View File

@ -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
) {
return creationContext.getJpaMetamodel().getAllowedEnumLiteralTexts().get( ctx.getText() );
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;
}

View File

@ -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

View File

@ -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
);

View File

@ -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(

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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
*/

View File

@ -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 );
if ( enumAnn != null ) {
enumType = enumAnn.value();
}
final Enumerated enumAnn = getAnnotation( reader.getAnnotationsMethod(), Enumerated.class );
if ( enumAnn != null ) {
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,9 +466,11 @@ public class EnumType<T extends Enum<T>>
return true;
}
for ( Annotation annotation : reader.getAnnotationsMethod() ) {
if ( annotation instanceof Nationalized ) {
return true;
if ( reader != null ) {
for ( Annotation annotation : reader.getAnnotationsMethod() ) {
if ( annotation instanceof Nationalized ) {
return true;
}
}
}

View File

@ -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() );
}
);
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -1,56 +1,56 @@
/*
* 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;
public class Person {
private long id;
private Gender gender;
private HairColor hairColor;
private HairColor originalHairColor;
public static Person person(Gender gender, HairColor hairColor) {
Person person = new Person();
person.setGender( gender );
person.setHairColor( hairColor );
return person;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public HairColor getHairColor() {
return hairColor;
}
public void setHairColor(HairColor hairColor) {
this.hairColor = hairColor;
}
public HairColor getOriginalHairColor() {
return originalHairColor;
}
public void setOriginalHairColor(HairColor originalHairColor) {
this.originalHairColor = originalHairColor;
}
}
/*
* 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;
public class Person {
private long id;
private Gender gender;
private HairColor hairColor;
private HairColor originalHairColor;
public static Person person(Gender gender, HairColor hairColor) {
Person person = new Person();
person.setGender( gender );
person.setHairColor( hairColor );
return person;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public HairColor getHairColor() {
return hairColor;
}
public void setHairColor(HairColor hairColor) {
this.hairColor = hairColor;
}
public HairColor getOriginalHairColor() {
return originalHairColor;
}
public void setOriginalHairColor(HairColor originalHairColor) {
this.originalHairColor = originalHairColor;
}
}

View File

@ -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 );
}
}

View File

@ -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;

View File

@ -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

View File

@ -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() );
} );
}
}

View File

@ -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 );
}
}
}

View File

@ -1,39 +1,39 @@
<?xml version="1.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>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.test.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="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>
</type>
</property>
<property name="originalHairColor">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">org.hibernate.test.enums.HairColor</param>
<param name="type">12</param>
</type>
</property>
</class>
<?xml version="1.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>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<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.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.orm.test.mapping.converted.enums.HairColor</param>
</type>
</property>
<property name="originalHairColor">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">org.hibernate.orm.test.mapping.converted.enums.HairColor</param>
<param name="type">12</param>
</type>
</property>
</class>
</hibernate-mapping>

View File

@ -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>

View File

@ -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