diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/JpaAttributeConverterCreationContext.java b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/JpaAttributeConverterCreationContext.java index 03a9bd34ef..69c5e61aff 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/JpaAttributeConverterCreationContext.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/JpaAttributeConverterCreationContext.java @@ -8,6 +8,7 @@ package org.hibernate.boot.model.convert.spi; import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry; +import org.hibernate.type.spi.TypeConfiguration; /** * Access to information that implementors of @@ -18,5 +19,9 @@ import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry; */ public interface JpaAttributeConverterCreationContext { ManagedBeanRegistry getManagedBeanRegistry(); - JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry(); + TypeConfiguration getTypeConfiguration(); + + default JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() { + return getTypeConfiguration().getJavaTypeDescriptorRegistry(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java index 2860493081..d0879d01e1 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java @@ -42,7 +42,6 @@ import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor; import org.hibernate.type.descriptor.java.RowVersionTypeDescriptor; import org.hibernate.type.descriptor.java.TemporalJavaTypeDescriptor; -import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; import org.hibernate.type.spi.TypeConfiguration; @@ -239,8 +238,8 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato } @Override - public JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() { - return typeConfiguration.getJavaTypeDescriptorRegistry(); + public TypeConfiguration getTypeConfiguration() { + return typeConfiguration; } }; @@ -408,8 +407,8 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato } @Override - public JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() { - return typeConfiguration.getJavaTypeDescriptorRegistry(); + public TypeConfiguration getTypeConfiguration() { + return typeConfiguration; } } ) diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java index 26a4cd640b..a617287aa6 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java @@ -44,8 +44,6 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter; import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.service.ServiceRegistry; -import org.hibernate.type.BinaryType; -import org.hibernate.type.RowVersionType; import org.hibernate.type.Type; import org.hibernate.type.descriptor.JdbcTypeNameMapper; import org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter; @@ -54,6 +52,7 @@ import org.hibernate.type.descriptor.java.BasicJavaDescriptor; import org.hibernate.type.descriptor.sql.LobTypeMappings; import org.hibernate.type.descriptor.sql.NationalizedTypeMappings; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.DynamicParameterizedType; /** @@ -579,8 +578,8 @@ public abstract class SimpleValue implements KeyValue { } @Override - public org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() { - return metadata.getTypeConfiguration().getJavaTypeDescriptorRegistry(); + public TypeConfiguration getTypeConfiguration() { + return getMetadata().getTypeConfiguration(); } } ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/JdbcMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/JdbcMapping.java index 4b9cb23c36..30eaa4c432 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/JdbcMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/JdbcMapping.java @@ -29,6 +29,7 @@ public interface JdbcMapping { */ SqlTypeDescriptor getSqlTypeDescriptor(); + /** * The strategy for extracting values of this expressable * type from JDBC ResultSets, CallableStatements, etc diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/convert/spi/EnumValueConverter.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/convert/spi/EnumValueConverter.java index 45ba41b0cd..00ed7c8640 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/convert/spi/EnumValueConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/convert/spi/EnumValueConverter.java @@ -11,6 +11,8 @@ import java.sql.SQLException; import org.hibernate.annotations.Remove; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.sql.ast.tree.select.SelectStatement; +import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor; /** @@ -26,7 +28,14 @@ public interface EnumValueConverter extends BasicValueConvert String toSqlLiteral(Object value); + /** + * @since 6.0 + * + * @deprecated Added temporarily in support of dual SQL execution until fully migrated + * to {@link SelectStatement} and {@link JdbcOperation} + */ @Remove + @Deprecated void writeValue( PreparedStatement statement, Enum value, diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 4f212e5436..ef6a404567 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -137,6 +137,7 @@ import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapp import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType; import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper; import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; +import org.hibernate.metamodel.model.convert.spi.BasicValueConverter; import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.spi.PersisterCreationContext; @@ -6056,14 +6057,38 @@ public abstract class AbstractEntityPersister final String[] attrColumnNames = getPropertyColumnNames( propertyIndex ); if ( attrType instanceof BasicType ) { - return new BasicValuedSingularAttributeMapping( - attrName, - tableExpression, - attrColumnNames[0], - ( (BasicValue) bootProperty.getValue() ).resolve().getValueConverter(), - (BasicType) attrType, - (BasicType) attrType - ); + final BasicValue.Resolution resolution = ( (BasicValue) bootProperty.getValue() ).resolve(); + final BasicValueConverter valueConverter = resolution.getValueConverter(); + + if ( valueConverter != null ) { + // we want to "decompose" the "type" into its various pieces as expected by the mapping + assert valueConverter.getRelationalJavaDescriptor() == resolution.getRelationalJavaDescriptor(); + + final BasicType mappingBasicType = creationProcess.getCreationContext() + .getDomainModel() + .getTypeConfiguration() + .getBasicTypeRegistry() + .resolve( valueConverter.getRelationalJavaDescriptor(), resolution.getRelationalSqlTypeDescriptor() ); + + return new BasicValuedSingularAttributeMapping( + attrName, + tableExpression, + attrColumnNames[0], + valueConverter, + mappingBasicType, + mappingBasicType.getJdbcMapping() + ); + } + else { + return new BasicValuedSingularAttributeMapping( + attrName, + tableExpression, + attrColumnNames[0], + null, + (BasicType) attrType, + (BasicType) attrType + ); + } } // todo (6.0) : for now ignore any non basic-typed attributes diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java index 06aa6025b8..0e2866f239 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/ColumnReference.java @@ -68,9 +68,7 @@ public class ColumnReference implements Expression { // todo (6.0) : potential use for runtime database model - interpretation of table and column references // into metadata info such as java/sql type, binder, extractor - final ValueExtractor jdbcValueExtractor = jdbcMapping.getJdbcValueExtractor(); - - return new SqlSelectionImpl( jdbcPosition, valuesArrayPosition, this, jdbcValueExtractor ); + return new SqlSelectionImpl( jdbcPosition, valuesArrayPosition, this, jdbcMapping ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/SqlSelectionImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/SqlSelectionImpl.java index 8ab85b5707..d7c9455671 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/SqlSelectionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/SqlSelectionImpl.java @@ -9,29 +9,42 @@ package org.hibernate.sql.results.internal; import java.util.Objects; import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SqlExpressable; import org.hibernate.sql.ast.spi.SqlAstWalker; import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.type.descriptor.ValueExtractor; /** + * @asciidoc + * + * ```` + * @Entity + * class MyEntity { + * ... + * @Column( name = "the_column", ... ) + * public String getTheColumn() { ... } + * + * @Convert( ... ) + * @Column( name = "the_column", ... ) + * ConvertedType getTheConvertedColumn() { ... } + * + * } + * ```` + * * @author Steve Ebersole */ public class SqlSelectionImpl implements SqlSelection { private final int jdbcPosition; private final int valuesArrayPosition; private final Expression sqlExpression; - private final ValueExtractor jdbcValueExtractor; + private final JdbcMapping jdbcMapping; public SqlSelectionImpl(int jdbcPosition, int valuesArrayPosition, Expression sqlExpression, JdbcMapping jdbcMapping) { - this( jdbcPosition, valuesArrayPosition, sqlExpression, jdbcMapping.getJdbcValueExtractor() ); - } - - public SqlSelectionImpl(int jdbcPosition, int valuesArrayPosition, Expression sqlExpression, ValueExtractor jdbcValueExtractor) { this.jdbcPosition = jdbcPosition; this.valuesArrayPosition = valuesArrayPosition; this.sqlExpression = sqlExpression; - this.jdbcValueExtractor = jdbcValueExtractor; + this.jdbcMapping = jdbcMapping; } public Expression getWrappedSqlExpression() { @@ -40,7 +53,9 @@ public class SqlSelectionImpl implements SqlSelection { @Override public ValueExtractor getJdbcValueExtractor() { - return jdbcValueExtractor; + return ( (SqlExpressable) sqlExpression.getExpressionType() ).getJdbcMapping().getJdbcValueExtractor(); +// return jdbcValueExtractor; +// return jdbcMapping.getJdbcValueExtractor(); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/SmokeTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/SmokeTests.java index 1e927bd04b..73c868e08e 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/SmokeTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/SmokeTests.java @@ -11,6 +11,7 @@ import java.util.List; import org.hibernate.cfg.AvailableSettings; import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity; +import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender; import org.hibernate.query.spi.QueryImplementor; import org.hibernate.testing.orm.junit.DomainModel; @@ -86,6 +87,21 @@ public class SmokeTests { ); } + @Test + public void testSelectGenderHql(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + final QueryImplementor query = session.createQuery( + "select e.gender from SimpleEntity e", + Gender.class + ); + List simpleEntities = query.list(); + assertThat( simpleEntities.size(), is( 1 ) ); + assertThat( simpleEntities.get( 0 ), is( FEMALE ) ); + } + ); + } + @Test @FailureExpected( reason = "Support for entity-values DomainResults not yet implemented") public void testSelectEntityHqlExecution(SessionFactoryScope scope) {