NativeQuery support
- support for `#addScalar(Class,AttributeConverter)` - support for `#addScalar(Class,Class<AttributeConverter>)` - fixed problem with mapping of converted enums
This commit is contained in:
parent
3b210c493f
commit
2f8f04747b
|
@ -0,0 +1,20 @@
|
|||
= Changes
|
||||
|
||||
Changes in 6.0 worth documenting in various places
|
||||
|
||||
|
||||
== New features
|
||||
|
||||
Document in release-notes:
|
||||
|
||||
* `@SqlTypeCode`
|
||||
* `@SqlType`
|
||||
* `@JavaType`
|
||||
* `NativeQuery#addScalar(Class)`
|
||||
* `NativeQuery#addScalar(Class,AttributeConverter)`
|
||||
* `NativeQuery#addScalar(Class,Class<AttributeConverter>)`
|
||||
|
||||
|
||||
== Changes
|
||||
|
||||
Document in migration-guide.
|
|
@ -173,7 +173,7 @@ public class InferredBasicValueResolver {
|
|||
|
||||
switch ( enumStyle ) {
|
||||
case STRING: {
|
||||
final JavaTypeDescriptor<String> relationalJtd;
|
||||
final JavaTypeDescriptor<?> relationalJtd;
|
||||
if ( explicitJavaType != null ) {
|
||||
if ( ! String.class.isAssignableFrom( explicitJavaType.getJavaType() ) ) {
|
||||
throw new MappingException(
|
||||
|
@ -182,11 +182,12 @@ public class InferredBasicValueResolver {
|
|||
" should handle `java.lang.String` as its relational type descriptor"
|
||||
);
|
||||
}
|
||||
//noinspection unchecked
|
||||
relationalJtd = explicitJavaType;
|
||||
}
|
||||
else {
|
||||
relationalJtd = typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||
final boolean useCharacter = stdIndicators.getColumnLength() == 1;
|
||||
final Class<?> relationalJavaType = useCharacter ? Character.class : String.class;
|
||||
relationalJtd = typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( relationalJavaType );
|
||||
}
|
||||
|
||||
final SqlTypeDescriptor std = explicitSqlType != null ? explicitSqlType : relationalJtd.getJdbcRecommendedSqlType( stdIndicators );
|
||||
|
|
|
@ -19,6 +19,8 @@ import org.hibernate.mapping.BasicValue;
|
|||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
@ -93,6 +95,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
|
|||
final JavaTypeDescriptor explicitJtd = explicitJtdAccess != null
|
||||
? explicitJtdAccess.apply( typeConfiguration )
|
||||
: null;
|
||||
|
||||
final JavaTypeDescriptor domainJtd = explicitJtd != null
|
||||
? explicitJtd
|
||||
: converter.getDomainJavaDescriptor();
|
||||
|
@ -100,7 +103,9 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
|
|||
final SqlTypeDescriptor explicitStd = explicitStdAccess != null
|
||||
? explicitStdAccess.apply( typeConfiguration )
|
||||
: null;
|
||||
|
||||
final JavaTypeDescriptor relationalJtd = converter.getRelationalJavaDescriptor();
|
||||
|
||||
final SqlTypeDescriptor relationalStd = explicitStd != null
|
||||
? explicitStd
|
||||
: relationalJtd.getJdbcRecommendedSqlType( sqlTypeIndicators );
|
||||
|
@ -139,13 +144,46 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
|
|||
SqlTypeDescriptor relationalStd,
|
||||
JpaAttributeConverter valueConverter,
|
||||
MutabilityPlan mutabilityPlan) {
|
||||
assert domainJtd != null;
|
||||
this.domainJtd = domainJtd;
|
||||
|
||||
assert relationalJtd != null;
|
||||
this.relationalJtd = relationalJtd;
|
||||
|
||||
assert relationalStd != null;
|
||||
this.relationalStd = relationalStd;
|
||||
|
||||
assert valueConverter != null;
|
||||
this.valueConverter = valueConverter;
|
||||
|
||||
assert mutabilityPlan != null;
|
||||
this.mutabilityPlan = mutabilityPlan;
|
||||
|
||||
this.jdbcMapping = new StandardBasicTypeImpl( relationalJtd, relationalStd ).getJdbcMapping();
|
||||
this.jdbcMapping = new JdbcMapping() {
|
||||
private final ValueExtractor extractor = relationalStd.getExtractor( relationalJtd );
|
||||
private final ValueBinder binder = relationalStd.getBinder( relationalJtd );
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||
return relationalJtd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getSqlTypeDescriptor() {
|
||||
return relationalStd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueExtractor getJdbcValueExtractor() {
|
||||
return extractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueBinder getJdbcValueBinder() {
|
||||
return binder;
|
||||
}
|
||||
};
|
||||
// this.jdbcMapping = new StandardBasicTypeImpl( relationalJtd, relationalStd );
|
||||
|
||||
this.legacyResolvedType = new AttributeConverterTypeAdapter(
|
||||
ConverterDescriptor.TYPE_NAME_PREFIX + valueConverter.getConverterJavaTypeDescriptor().getJavaType().getName(),
|
||||
|
@ -156,8 +194,7 @@ public class NamedConverterResolution<J> implements BasicValue.Resolution<J> {
|
|||
),
|
||||
valueConverter,
|
||||
relationalStd,
|
||||
domainJtd.getJavaType(),
|
||||
relationalJtd.getJavaType(),
|
||||
relationalJtd,
|
||||
domainJtd
|
||||
);
|
||||
}
|
||||
|
|
|
@ -167,6 +167,17 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
|
|||
return column;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getColumnLength() {
|
||||
if ( column != null && column instanceof Column ) {
|
||||
final Long length = ( (Column) column ).getLength();
|
||||
return length == null ? NO_COLUMN_LENGTH : length;
|
||||
}
|
||||
else {
|
||||
return NO_COLUMN_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColumn(Column incomingColumn) {
|
||||
super.addColumn( incomingColumn );
|
||||
|
@ -330,7 +341,6 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
JavaTypeDescriptor jtd = null;
|
||||
|
||||
// determine JTD if we can
|
||||
|
|
|
@ -576,7 +576,7 @@ public abstract class SimpleValue implements KeyValue {
|
|||
}
|
||||
);
|
||||
|
||||
final BasicJavaDescriptor entityAttributeJavaTypeDescriptor = (BasicJavaDescriptor) jpaAttributeConverter.getDomainJavaTypeDescriptor();
|
||||
final BasicJavaDescriptor<?> domainJtd = (BasicJavaDescriptor<?>) jpaAttributeConverter.getDomainJavaTypeDescriptor();
|
||||
|
||||
|
||||
// build the SqlTypeDescriptor adapter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -595,7 +595,7 @@ public abstract class SimpleValue implements KeyValue {
|
|||
jdbcTypeCode = LobTypeMappings.getLobCodeTypeMapping( jdbcTypeCode );
|
||||
}
|
||||
else {
|
||||
if ( Serializable.class.isAssignableFrom( entityAttributeJavaTypeDescriptor.getJavaType() ) ) {
|
||||
if ( Serializable.class.isAssignableFrom( domainJtd.getJavaType() ) ) {
|
||||
jdbcTypeCode = Types.BLOB;
|
||||
}
|
||||
else {
|
||||
|
@ -642,19 +642,18 @@ public abstract class SimpleValue implements KeyValue {
|
|||
jpaAttributeConverter.getDomainJavaTypeDescriptor().getJavaType().getSimpleName(),
|
||||
jpaAttributeConverter.getRelationalJavaTypeDescriptor().getJavaType().getSimpleName()
|
||||
);
|
||||
return new AttributeConverterTypeAdapter(
|
||||
return new AttributeConverterTypeAdapter<>(
|
||||
name,
|
||||
description,
|
||||
jpaAttributeConverter,
|
||||
sqlTypeDescriptorAdapter,
|
||||
jpaAttributeConverter.getDomainJavaTypeDescriptor().getJavaType(),
|
||||
jpaAttributeConverter.getRelationalJavaTypeDescriptor().getJavaType(),
|
||||
entityAttributeJavaTypeDescriptor
|
||||
jpaAttributeConverter.getRelationalJavaTypeDescriptor(),
|
||||
jpaAttributeConverter.getDomainJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isTypeSpecified() {
|
||||
return typeName!=null;
|
||||
return typeName != null;
|
||||
}
|
||||
|
||||
public void setTypeParameters(Properties parameterMap) {
|
||||
|
@ -752,11 +751,15 @@ public abstract class SimpleValue implements KeyValue {
|
|||
|
||||
private void createParameterImpl() {
|
||||
try {
|
||||
String[] columnsNames = new String[columns.size()];
|
||||
final String[] columnNames = new String[ columns.size() ];
|
||||
final Long[] columnLengths = new Long[ columns.size() ];
|
||||
|
||||
for ( int i = 0; i < columns.size(); i++ ) {
|
||||
Selectable column = columns.get(i);
|
||||
if (column instanceof Column){
|
||||
columnsNames[i] = ((Column) column).getName();
|
||||
final Selectable selectable = columns.get(i);
|
||||
if ( selectable instanceof Column ) {
|
||||
final Column column = (Column) selectable;
|
||||
columnNames[i] = column.getName();
|
||||
columnLengths[i] = column.getLength();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -781,7 +784,8 @@ public abstract class SimpleValue implements KeyValue {
|
|||
table.getSchema(),
|
||||
table.getName(),
|
||||
Boolean.valueOf( typeParameters.getProperty( DynamicParameterizedType.IS_PRIMARY_KEY ) ),
|
||||
columnsNames
|
||||
columnNames,
|
||||
columnLengths
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -799,9 +803,17 @@ public abstract class SimpleValue implements KeyValue {
|
|||
private final String table;
|
||||
private final boolean primaryKey;
|
||||
private final String[] columns;
|
||||
private final Long[] columnLengths;
|
||||
|
||||
private ParameterTypeImpl(Class returnedClass, Annotation[] annotationsMethod, String catalog, String schema,
|
||||
String table, boolean primaryKey, String[] columns) {
|
||||
private ParameterTypeImpl(
|
||||
Class returnedClass,
|
||||
Annotation[] annotationsMethod,
|
||||
String catalog,
|
||||
String schema,
|
||||
String table,
|
||||
boolean primaryKey,
|
||||
String[] columns,
|
||||
Long[] columnLengths) {
|
||||
this.returnedClass = returnedClass;
|
||||
this.annotationsMethod = annotationsMethod;
|
||||
this.catalog = catalog;
|
||||
|
@ -809,6 +821,7 @@ public abstract class SimpleValue implements KeyValue {
|
|||
this.table = table;
|
||||
this.primaryKey = primaryKey;
|
||||
this.columns = columns;
|
||||
this.columnLengths = columnLengths;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -845,5 +858,10 @@ public abstract class SimpleValue implements KeyValue {
|
|||
public String[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long[] getColumnLengths() {
|
||||
return columnLengths;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.metamodel.model.convert;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Factory for converter instances
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Converters {
|
||||
public static <O,R> BasicValueConverter<O,R> jpaAttributeConverter(
|
||||
JavaTypeDescriptor<R> relationalJtd,
|
||||
JavaTypeDescriptor<O> domainJtd,
|
||||
Class<? extends AttributeConverter<O,R>> converterClass,
|
||||
SessionFactory factory) {
|
||||
final SessionFactoryImplementor sfi = (SessionFactoryImplementor) factory;
|
||||
|
||||
final ManagedBeanRegistry beanRegistry = sfi.getServiceRegistry().getService( ManagedBeanRegistry.class );
|
||||
final ManagedBean<? extends AttributeConverter<O, R>> converterBean = beanRegistry.getBean( converterClass );
|
||||
|
||||
final TypeConfiguration typeConfiguration = sfi.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
final JavaTypeDescriptor<? extends AttributeConverter<O, R>> converterJtd = jtdRegistry.getDescriptor( converterClass );
|
||||
|
||||
return new JpaAttributeConverterImpl<>( converterBean, converterJtd, domainJtd, relationalJtd );
|
||||
}
|
||||
|
||||
private Converters() {
|
||||
}
|
||||
}
|
|
@ -18,14 +18,14 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R> {
|
||||
private final ManagedBean<AttributeConverter<O,R>> attributeConverterBean;
|
||||
private final JavaTypeDescriptor<AttributeConverter<O, R>> converterJavaTypeDescriptor;
|
||||
private final ManagedBean<? extends AttributeConverter<O,R>> attributeConverterBean;
|
||||
private final JavaTypeDescriptor<? extends AttributeConverter<O, R>> converterJavaTypeDescriptor;
|
||||
private final JavaTypeDescriptor<O> domainJavaTypeDescriptor;
|
||||
private final JavaTypeDescriptor<R> relationalJavaTypeDescriptor;
|
||||
|
||||
public JpaAttributeConverterImpl(
|
||||
ManagedBean<AttributeConverter<O, R>> attributeConverterBean,
|
||||
JavaTypeDescriptor<AttributeConverter<O,R>> converterJavaTypeDescriptor,
|
||||
ManagedBean<? extends AttributeConverter<O, R>> attributeConverterBean,
|
||||
JavaTypeDescriptor<? extends AttributeConverter<O,R>> converterJavaTypeDescriptor,
|
||||
JavaTypeDescriptor<O> domainJavaTypeDescriptor,
|
||||
JavaTypeDescriptor<R> relationalJavaTypeDescriptor) {
|
||||
this.attributeConverterBean = attributeConverterBean;
|
||||
|
@ -35,7 +35,7 @@ public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R
|
|||
}
|
||||
|
||||
@Override
|
||||
public ManagedBean<AttributeConverter<O, R>> getConverterBean() {
|
||||
public ManagedBean<? extends AttributeConverter<O, R>> getConverterBean() {
|
||||
return attributeConverterBean;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R
|
|||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<AttributeConverter<O, R>> getConverterJavaTypeDescriptor() {
|
||||
public JavaTypeDescriptor<? extends AttributeConverter<O, R>> getConverterJavaTypeDescriptor() {
|
||||
return converterJavaTypeDescriptor;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public class NamedEnumValueConverter<E extends Enum<E>> implements EnumValueConv
|
|||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.VARCHAR;
|
||||
return sqlTypeDescriptor.getJdbcTypeCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,9 +17,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JpaAttributeConverter<O,R> extends BasicValueConverter<O,R> {
|
||||
JavaTypeDescriptor<AttributeConverter<O,R>> getConverterJavaTypeDescriptor();
|
||||
JavaTypeDescriptor<? extends AttributeConverter<O,R>> getConverterJavaTypeDescriptor();
|
||||
|
||||
ManagedBean<AttributeConverter<O,R>> getConverterBean();
|
||||
ManagedBean<? extends AttributeConverter<O,R>> getConverterBean();
|
||||
|
||||
JavaTypeDescriptor<O> getDomainJavaTypeDescriptor();
|
||||
JavaTypeDescriptor<R> getRelationalJavaTypeDescriptor();
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Calendar;
|
|||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.FlushModeType;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.Parameter;
|
||||
|
@ -76,20 +77,6 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
|
|||
*/
|
||||
NativeQuery<T> addScalar(String columnAlias);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result.
|
||||
* <p/>
|
||||
* Functions like {@code <return-scalar/>} in {@code hbm.xml} or
|
||||
* {@link javax.persistence.ColumnResult} in annotations
|
||||
*
|
||||
* @param columnAlias The column alias in the result-set to be processed
|
||||
* as a scalar result
|
||||
* @param type The Hibernate type as which to treat the value.
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
// NativeQuery<T> addScalar(String columnAlias, Type type);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result.
|
||||
* <p/>
|
||||
|
@ -105,12 +92,45 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
|
|||
NativeQuery<T> addScalar(String columnAlias, BasicDomainType type);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result with an explicit return type
|
||||
* Declare a scalar query result using the specified result type.
|
||||
*
|
||||
* Hibernate will implicitly determine an appropriate conversion, if
|
||||
* it can. Otherwise an exception will be thrown
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
NativeQuery<T> addScalar(String columnAlias, Class<?> javaType);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result with an explicit conversion
|
||||
*
|
||||
* @param relationalJavaType The Java type expected by the converter as its
|
||||
* "relational" type.
|
||||
* @param converter The conversion to apply. Consumes the JDBC value based
|
||||
* on `relationalJavaType`.
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
<C> NativeQuery<T> addScalar(String columnAlias, Class<C> relationalJavaType, AttributeConverter<?,C> converter);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result with an explicit conversion
|
||||
*
|
||||
* @param relationalJavaType The Java type expected by the converter as its
|
||||
* "relational" type.
|
||||
* @param converter The conversion to apply. Consumes the JDBC value based
|
||||
* on `relationalJavaType`.
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
<C> NativeQuery<T> addScalar(String columnAlias, Class<C> relationalJavaType, Class<? extends AttributeConverter<?,C>> converter);
|
||||
|
||||
/**
|
||||
* Add a new root return mapping, returning a {@link RootReturn} to allow
|
||||
* further definition.
|
||||
|
|
|
@ -6,55 +6,62 @@
|
|||
*/
|
||||
package org.hibernate.query.results;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Builders {
|
||||
public static ScalarResultBuilder scalar(String columnAlias) {
|
||||
return new ScalarResultBuilder( columnAlias );
|
||||
return new StandardScalarResultBuilder( columnAlias );
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(
|
||||
String columnAlias,
|
||||
BasicType<?> type) {
|
||||
return new ScalarResultBuilder( columnAlias, type );
|
||||
return new StandardScalarResultBuilder( columnAlias, type );
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(
|
||||
String columnAlias,
|
||||
Class<?> javaType,
|
||||
SessionFactoryImplementor factory) {
|
||||
return new ScalarResultBuilder(
|
||||
columnAlias,
|
||||
factory.getTypeConfiguration().standardBasicTypeForJavaType( javaType )
|
||||
);
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = factory.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( javaType );
|
||||
|
||||
return new StandardScalarResultBuilder( columnAlias, javaTypeDescriptor );
|
||||
}
|
||||
|
||||
public static DomainResult<?> implicitScalarDomainResult(
|
||||
int colIndex,
|
||||
String columnName,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
public static <C> ResultBuilder scalar(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
AttributeConverter<?, C> converter,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( colIndex );
|
||||
final BasicJavaDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
final BasicType<?> jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||
sqlSelectionConsumer.accept( new SqlSelectionImpl( colIndex, jdbcMapping ) );
|
||||
return new BasicResult<>( colIndex, columnName, javaTypeDescriptor );
|
||||
return ConvertedResultBuilder.from( columnAlias, relationalJavaType, converter, sessionFactory );
|
||||
}
|
||||
|
||||
public static <C> ResultBuilder scalar(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
Class<? extends AttributeConverter<?, C>> converterJavaType,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return ConvertedResultBuilder.from( columnAlias, relationalJavaType, converterJavaType, sessionFactory );
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(int position) {
|
||||
// will be needed for interpreting legacy HBM <resultset/> mappings
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(int position, BasicType<?> type) {
|
||||
// will be needed for interpreting legacy HBM <resultset/> mappings
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
public static EntityResultBuilder entity(String tableAlias, String entityName) {
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* 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.query.results;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.converter.ConvertedValueExtractor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* A ResultBuilder for explicitly converted scalar results
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConvertedResultBuilder implements ScalarResultBuilder {
|
||||
|
||||
public static <C> ResultBuilder from(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
AttributeConverter<?, C> converter,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
final JavaTypeDescriptor<C> relationJtd = jtdRegistry.getDescriptor( relationalJavaType );
|
||||
|
||||
return new ConvertedResultBuilder( columnAlias, relationJtd, converter );
|
||||
}
|
||||
|
||||
public static <C> ResultBuilder from(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
Class<? extends AttributeConverter<?, C>> converterJavaType,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
final JavaTypeDescriptor<C> relationJtd = jtdRegistry.getDescriptor( relationalJavaType );
|
||||
|
||||
final ManagedBeanRegistry beans = sessionFactory.getServiceRegistry().getService( ManagedBeanRegistry.class );
|
||||
final ManagedBean<? extends AttributeConverter<?, C>> bean = beans.getBean( converterJavaType );
|
||||
final AttributeConverter<?, C> converter = bean.getBeanInstance();
|
||||
|
||||
return new ConvertedResultBuilder( columnAlias, relationJtd, converter );
|
||||
}
|
||||
|
||||
private final String columnAlias;
|
||||
private final JavaTypeDescriptor<?> relationJtd;
|
||||
private final AttributeConverter<?,?> converter;
|
||||
|
||||
public ConvertedResultBuilder(
|
||||
String columnAlias,
|
||||
JavaTypeDescriptor<?> relationJtd,
|
||||
AttributeConverter<?, ?> converter) {
|
||||
assert columnAlias != null;
|
||||
this.columnAlias = columnAlias;
|
||||
|
||||
assert relationJtd != null;
|
||||
this.relationJtd = relationJtd;
|
||||
|
||||
assert converter != null;
|
||||
this.converter = converter;
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
|
||||
final int valuesArrayPosition = jdbcPosition - 1;
|
||||
|
||||
final SqlTypeDescriptor std = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
|
||||
final ConverterMapping<Object> converterMapping = new ConverterMapping(
|
||||
relationJtd,
|
||||
std,
|
||||
new ConvertedValueExtractor( std.getExtractor( relationJtd ), converter )
|
||||
);
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, converterMapping );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult( valuesArrayPosition, columnAlias, converterMapping.getJavaTypeDescriptor() );
|
||||
}
|
||||
|
||||
|
||||
private static class ConverterMapping<T> implements MappingModelExpressable<T>, JdbcMapping {
|
||||
private final JavaTypeDescriptor<T> jtd;
|
||||
private final SqlTypeDescriptor std;
|
||||
|
||||
private final ValueExtractor<T> extractor;
|
||||
|
||||
public ConverterMapping(
|
||||
JavaTypeDescriptor<T> jtd,
|
||||
SqlTypeDescriptor std,
|
||||
ValueExtractor<T> extractor) {
|
||||
this.jtd = jtd;
|
||||
this.std = std;
|
||||
this.extractor = extractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCount(TypeConfiguration typeConfiguration) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<T> getJavaTypeDescriptor() {
|
||||
return jtd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getSqlTypeDescriptor() {
|
||||
return std;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueExtractor<T> getJdbcValueExtractor() {
|
||||
return extractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueBinder<?> getJdbcValueBinder() {
|
||||
// this will never get used for binding values
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
||||
return Collections.singletonList( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(
|
||||
Consumer<JdbcMapping> action,
|
||||
Clause clause,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
action.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class SqlSelectionImpl implements SqlSelection {
|
||||
private final int valuesArrayPosition;
|
||||
private final ConverterMapping converterMapping;
|
||||
|
||||
public SqlSelectionImpl(
|
||||
int valuesArrayPosition,
|
||||
ConverterMapping converterMapping) {
|
||||
this.valuesArrayPosition = valuesArrayPosition;
|
||||
this.converterMapping = converterMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getValuesArrayPosition() {
|
||||
return valuesArrayPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueExtractor getJdbcValueExtractor() {
|
||||
return converterMapping.getJdbcValueExtractor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return converterMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlAstWalker) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,96 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.query.results;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @see javax.persistence.ColumnResult
|
||||
* Nominal extension to ResultBuilder for cases involving scalar results
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ScalarResultBuilder implements ResultBuilder {
|
||||
private final String explicitName;
|
||||
|
||||
private final BasicType<?> explicitType;
|
||||
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
|
||||
|
||||
ScalarResultBuilder(String explicitName, BasicType<?> explicitType) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
assert explicitType != null;
|
||||
this.explicitType = explicitType;
|
||||
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
ScalarResultBuilder(String explicitName, JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
assert explicitJavaTypeDescriptor != null;
|
||||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
|
||||
this.explicitType = null;
|
||||
}
|
||||
|
||||
public ScalarResultBuilder(String explicitName) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
this.explicitType = null;
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public String getExplicitName() {
|
||||
return explicitName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( explicitName );
|
||||
final int valuesArrayPosition = jdbcPosition - 1;
|
||||
|
||||
final BasicType<?> jdbcMapping;
|
||||
|
||||
if ( explicitType != null ) {
|
||||
jdbcMapping = explicitType;
|
||||
}
|
||||
else if ( explicitJavaTypeDescriptor != null ) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( explicitJavaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
else {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult( valuesArrayPosition, explicitName, jdbcMapping.getJavaTypeDescriptor() );
|
||||
}
|
||||
|
||||
public interface ScalarResultBuilder extends ResultBuilder {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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.query.results;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @see javax.persistence.ColumnResult
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardScalarResultBuilder implements ScalarResultBuilder {
|
||||
private final String explicitName;
|
||||
|
||||
private final BasicType<?> explicitType;
|
||||
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
|
||||
|
||||
public StandardScalarResultBuilder(String explicitName) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
this.explicitType = null;
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
StandardScalarResultBuilder(String explicitName, BasicType<?> explicitType) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
assert explicitType != null;
|
||||
this.explicitType = explicitType;
|
||||
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
StandardScalarResultBuilder(String explicitName, JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
assert explicitJavaTypeDescriptor != null;
|
||||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
|
||||
this.explicitType = null;
|
||||
}
|
||||
|
||||
StandardScalarResultBuilder(JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
|
||||
assert explicitJavaTypeDescriptor != null;
|
||||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
|
||||
this.explicitName = null;
|
||||
this.explicitType = null;
|
||||
}
|
||||
|
||||
public String getExplicitName() {
|
||||
return explicitName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( explicitName );
|
||||
final int valuesArrayPosition = jdbcPosition - 1;
|
||||
|
||||
final BasicType<?> jdbcMapping;
|
||||
|
||||
if ( explicitType != null ) {
|
||||
jdbcMapping = explicitType;
|
||||
}
|
||||
else if ( explicitJavaTypeDescriptor != null ) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( explicitJavaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
else {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult( valuesArrayPosition, explicitName, jdbcMapping.getJavaTypeDescriptor() );
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.FlushModeType;
|
||||
|
@ -58,6 +59,7 @@ import org.hibernate.query.internal.QueryParameterBindingsImpl;
|
|||
import org.hibernate.query.results.Builders;
|
||||
import org.hibernate.query.results.EntityResultBuilder;
|
||||
import org.hibernate.query.results.LegacyFetchBuilder;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultSetMappingImpl;
|
||||
import org.hibernate.query.spi.AbstractQuery;
|
||||
import org.hibernate.query.spi.MutableQueryOptions;
|
||||
|
@ -475,22 +477,41 @@ public class NativeQueryImpl<R>
|
|||
|
||||
@Override
|
||||
public NativeQueryImplementor<R> addScalar(String columnAlias) {
|
||||
resultSetMapping.addResultBuilder( Builders.scalar( columnAlias ) );
|
||||
return registerBuilder( Builders.scalar( columnAlias ) );
|
||||
}
|
||||
|
||||
protected NativeQueryImplementor<R> registerBuilder(ResultBuilder builder) {
|
||||
resultSetMapping.addResultBuilder( builder );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type) {
|
||||
resultSetMapping.addResultBuilder( Builders.scalar( columnAlias, (BasicType<?>) type ) );
|
||||
return this;
|
||||
return registerBuilder( Builders.scalar( columnAlias, (BasicType<?>) type ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQueryImplementor<R> addScalar(String columnAlias, Class<?> javaType) {
|
||||
resultSetMapping.addResultBuilder( Builders.scalar( columnAlias, javaType, getSessionFactory() ) );
|
||||
return this;
|
||||
return registerBuilder( Builders.scalar( columnAlias, javaType, getSessionFactory() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C> NativeQueryImplementor<R> addScalar(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
AttributeConverter<?, C> converter) {
|
||||
return registerBuilder( Builders.scalar( columnAlias, relationalJavaType, converter, getSessionFactory() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C> NativeQueryImplementor<R> addScalar(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
Class<? extends AttributeConverter<?, C>> converter) {
|
||||
return registerBuilder( Builders.scalar( columnAlias, relationalJavaType, converter, getSessionFactory() ) );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EntityResultBuilder addRoot(String tableAlias, String entityName) {
|
||||
final EntityResultBuilder resultBuilder = Builders.entity(
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Calendar;
|
|||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.FlushModeType;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.Parameter;
|
||||
|
@ -58,6 +59,12 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
|
|||
@Override
|
||||
NativeQueryImplementor<R> addScalar(String columnAlias, Class<?> javaType);
|
||||
|
||||
@Override
|
||||
<C> NativeQueryImplementor<R> addScalar(String columnAlias, Class<C> relationalJavaType, AttributeConverter<?,C> converter);
|
||||
|
||||
@Override
|
||||
<C> NativeQueryImplementor<R> addScalar(String columnAlias, Class<C> relationalJavaType, Class<? extends AttributeConverter<?,C>> converter);
|
||||
|
||||
@Override
|
||||
EntityResultBuilder addRoot(String tableAlias, String entityName);
|
||||
|
||||
|
|
|
@ -306,7 +306,7 @@ public abstract class AbstractStandardBasicType<T>
|
|||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected final void nullSafeSet(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
|
||||
protected void nullSafeSet(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
|
||||
remapSqlTypeDescriptor( options ).getBinder( javaTypeDescriptor ).bind( st, ( T ) value, index, options );
|
||||
}
|
||||
|
||||
|
@ -430,6 +430,16 @@ public abstract class AbstractStandardBasicType<T>
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(
|
||||
PreparedStatement st,
|
||||
Object value,
|
||||
int index,
|
||||
boolean[] settable,
|
||||
SharedSessionContractImplementor session) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(CallableStatement st, Object value, String name, SharedSessionContractImplementor session) throws SQLException {
|
||||
nullSafeSet( st, value, name, (WrapperOptions) session );
|
||||
|
|
|
@ -64,7 +64,7 @@ import org.jboss.logging.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class EnumType<T extends Enum>
|
||||
public class EnumType<T extends Enum<T>>
|
||||
implements EnhancedUserType, DynamicParameterizedType, LoggableUserType, TypeConfigurationAware, Serializable {
|
||||
private static final Logger LOG = CoreLogging.logger( EnumType.class );
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class EnumType<T extends Enum>
|
|||
|
||||
private Class<T> enumClass;
|
||||
|
||||
private EnumValueConverter enumValueConverter;
|
||||
private EnumValueConverter<T,?> enumValueConverter;
|
||||
|
||||
private TypeConfiguration typeConfiguration;
|
||||
|
||||
|
@ -106,6 +106,8 @@ public class EnumType<T extends Enum>
|
|||
if ( reader != null ) {
|
||||
enumClass = reader.getReturnedClass().asSubclass( Enum.class );
|
||||
|
||||
final Long columnLength = reader.getColumnLengths()[0];
|
||||
|
||||
final boolean isOrdinal;
|
||||
final javax.persistence.EnumType enumType = getEnumType( reader );
|
||||
if ( enumType == null ) {
|
||||
|
@ -125,28 +127,31 @@ public class EnumType<T extends Enum>
|
|||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( enumClass );
|
||||
|
||||
final BasicJavaDescriptor<?> relationalJavaDescriptor = resolveRelationalJavaTypeDescriptor(
|
||||
reader,
|
||||
final LocalSqlTypeDescriptorIndicators indicators = new LocalSqlTypeDescriptorIndicators(
|
||||
enumType,
|
||||
columnLength,
|
||||
reader
|
||||
);
|
||||
|
||||
final BasicJavaDescriptor<?> relationalJtd = resolveRelationalJavaTypeDescriptor(
|
||||
indicators,
|
||||
enumJavaDescriptor
|
||||
);
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = relationalJavaDescriptor.getJdbcRecommendedSqlType(
|
||||
new LocalSqlTypeDescriptorIndicators( enumType, reader )
|
||||
);
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = relationalJtd.getJdbcRecommendedSqlType( indicators );
|
||||
|
||||
if ( isOrdinal ) {
|
||||
this.enumValueConverter = new OrdinalEnumValueConverter(
|
||||
enumJavaDescriptor,
|
||||
sqlTypeDescriptor,
|
||||
relationalJavaDescriptor
|
||||
relationalJtd
|
||||
);
|
||||
}
|
||||
else {
|
||||
this.enumValueConverter = new NamedEnumValueConverter(
|
||||
enumJavaDescriptor,
|
||||
sqlTypeDescriptor,
|
||||
relationalJavaDescriptor
|
||||
relationalJtd
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -172,10 +177,9 @@ public class EnumType<T extends Enum>
|
|||
}
|
||||
|
||||
private BasicJavaDescriptor<?> resolveRelationalJavaTypeDescriptor(
|
||||
ParameterType reader,
|
||||
javax.persistence.EnumType enumType, EnumJavaTypeDescriptor enumJavaDescriptor) {
|
||||
return enumJavaDescriptor.getJdbcRecommendedSqlType( new LocalSqlTypeDescriptorIndicators( enumType, reader ) )
|
||||
.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
LocalSqlTypeDescriptorIndicators indicators,
|
||||
EnumJavaTypeDescriptor<?> enumJavaDescriptor) {
|
||||
return enumJavaDescriptor.getJdbcRecommendedSqlType( indicators ).getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
}
|
||||
|
||||
private javax.persistence.EnumType getEnumType(ParameterType reader) {
|
||||
|
@ -204,21 +208,26 @@ public class EnumType<T extends Enum>
|
|||
return null;
|
||||
}
|
||||
|
||||
private EnumValueConverter interpretParameters(Properties parameters) {
|
||||
final EnumJavaTypeDescriptor enumJavaDescriptor = (EnumJavaTypeDescriptor) typeConfiguration
|
||||
private EnumValueConverter<T,?> interpretParameters(Properties parameters) {
|
||||
final EnumJavaTypeDescriptor<?> enumJavaDescriptor = (EnumJavaTypeDescriptor<?>) typeConfiguration
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( enumClass );
|
||||
|
||||
final ParameterType reader = (ParameterType) parameters.get( PARAMETER_TYPE );
|
||||
final javax.persistence.EnumType enumType = getEnumType( reader );
|
||||
final LocalSqlTypeDescriptorIndicators localIndicators = new LocalSqlTypeDescriptorIndicators( enumType, reader );
|
||||
|
||||
final BasicJavaDescriptor stringJavaDescriptor = (BasicJavaDescriptor) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||
final BasicJavaDescriptor integerJavaDescriptor = (BasicJavaDescriptor) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Integer.class );
|
||||
final LocalSqlTypeDescriptorIndicators localIndicators = new LocalSqlTypeDescriptorIndicators(
|
||||
enumType,
|
||||
reader.getColumnLengths()[0],
|
||||
reader
|
||||
);
|
||||
final BasicJavaDescriptor<?> stringJavaDescriptor = (BasicJavaDescriptor<?>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||
final BasicJavaDescriptor<?> integerJavaDescriptor = (BasicJavaDescriptor<?>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Integer.class );
|
||||
|
||||
if ( parameters.containsKey( NAMED ) ) {
|
||||
final boolean useNamed = ConfigurationHelper.getBoolean( NAMED, parameters );
|
||||
if ( useNamed ) {
|
||||
//noinspection rawtypes
|
||||
return new NamedEnumValueConverter(
|
||||
enumJavaDescriptor,
|
||||
stringJavaDescriptor.getJdbcRecommendedSqlType( localIndicators ),
|
||||
|
@ -226,6 +235,7 @@ public class EnumType<T extends Enum>
|
|||
);
|
||||
}
|
||||
else {
|
||||
//noinspection rawtypes
|
||||
return new OrdinalEnumValueConverter(
|
||||
enumJavaDescriptor,
|
||||
integerJavaDescriptor.getJdbcRecommendedSqlType( localIndicators ),
|
||||
|
@ -237,6 +247,7 @@ public class EnumType<T extends Enum>
|
|||
if ( parameters.containsKey( TYPE ) ) {
|
||||
final int type = Integer.decode( (String) parameters.get( TYPE ) );
|
||||
if ( isNumericType( type ) ) {
|
||||
//noinspection rawtypes
|
||||
return new OrdinalEnumValueConverter(
|
||||
enumJavaDescriptor,
|
||||
integerJavaDescriptor.getJdbcRecommendedSqlType( localIndicators ),
|
||||
|
@ -244,6 +255,7 @@ public class EnumType<T extends Enum>
|
|||
);
|
||||
}
|
||||
else if ( isCharacterType( type ) ) {
|
||||
//noinspection rawtypes
|
||||
return new NamedEnumValueConverter(
|
||||
enumJavaDescriptor,
|
||||
stringJavaDescriptor.getJdbcRecommendedSqlType( localIndicators ),
|
||||
|
@ -336,7 +348,7 @@ public class EnumType<T extends Enum>
|
|||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
|
||||
verifyConfigured();
|
||||
enumValueConverter.writeValue( st, (Enum) value, index, session );
|
||||
enumValueConverter.writeValue( st, (T) value, index, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -383,7 +395,7 @@ public class EnumType<T extends Enum>
|
|||
@Override
|
||||
public String toXMLString(Object value) {
|
||||
verifyConfigured();
|
||||
return (String) enumValueConverter.getDomainJavaDescriptor().unwrap( (Enum) value, String.class, null );
|
||||
return enumValueConverter.getDomainJavaDescriptor().unwrap( (T) value, String.class, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -396,7 +408,7 @@ public class EnumType<T extends Enum>
|
|||
@Override
|
||||
public String toLoggableString(Object value, SessionFactoryImplementor factory) {
|
||||
verifyConfigured();
|
||||
return enumValueConverter.getDomainJavaDescriptor().toString( (Enum) value );
|
||||
return enumValueConverter.getDomainJavaDescriptor().toString( (T) value );
|
||||
}
|
||||
|
||||
public boolean isOrdinal() {
|
||||
|
@ -406,10 +418,12 @@ public class EnumType<T extends Enum>
|
|||
|
||||
private class LocalSqlTypeDescriptorIndicators implements SqlTypeDescriptorIndicators {
|
||||
private final javax.persistence.EnumType enumType;
|
||||
private final Long columnLength;
|
||||
private final ParameterType reader;
|
||||
|
||||
public LocalSqlTypeDescriptorIndicators(javax.persistence.EnumType enumType, ParameterType reader) {
|
||||
public LocalSqlTypeDescriptorIndicators(javax.persistence.EnumType enumType, Long columnLength, ParameterType reader) {
|
||||
this.enumType = enumType;
|
||||
this.columnLength = columnLength;
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
|
@ -444,5 +458,10 @@ public class EnumType<T extends Enum>
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getColumnLength() {
|
||||
return columnLength == null ? NO_COLUMN_LENGTH : columnLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,17 @@
|
|||
*/
|
||||
package org.hibernate.type.descriptor.converter;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
|
@ -24,13 +32,14 @@ import org.jboss.logging.Logger;
|
|||
public class AttributeConverterTypeAdapter<T> extends AbstractSingleColumnStandardBasicType<T> {
|
||||
private static final Logger log = Logger.getLogger( AttributeConverterTypeAdapter.class );
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static final String NAME_PREFIX = ConverterDescriptor.TYPE_NAME_PREFIX;
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private final Class modelType;
|
||||
private final Class jdbcType;
|
||||
private final JavaTypeDescriptor<T> domainJtd;
|
||||
private final JavaTypeDescriptor<?> relationalJtd;
|
||||
private final JpaAttributeConverter<? extends T,?> attributeConverter;
|
||||
|
||||
private final MutabilityPlan<T> mutabilityPlan;
|
||||
|
@ -40,24 +49,22 @@ public class AttributeConverterTypeAdapter<T> extends AbstractSingleColumnStanda
|
|||
String name,
|
||||
String description,
|
||||
JpaAttributeConverter<? extends T,?> attributeConverter,
|
||||
SqlTypeDescriptor sqlTypeDescriptorAdapter,
|
||||
Class modelType,
|
||||
Class jdbcType,
|
||||
JavaTypeDescriptor<T> entityAttributeJavaTypeDescriptor) {
|
||||
super( sqlTypeDescriptorAdapter, entityAttributeJavaTypeDescriptor );
|
||||
SqlTypeDescriptor std,
|
||||
JavaTypeDescriptor<?> relationalJtd,
|
||||
JavaTypeDescriptor<T> domainJtd) {
|
||||
//noinspection rawtypes
|
||||
super( std, (JavaTypeDescriptor) relationalJtd );
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.modelType = modelType;
|
||||
this.jdbcType = jdbcType;
|
||||
this.domainJtd = domainJtd;
|
||||
this.relationalJtd = relationalJtd;
|
||||
this.attributeConverter = attributeConverter;
|
||||
|
||||
this.mutabilityPlan = entityAttributeJavaTypeDescriptor.getMutabilityPlan().isMutable()
|
||||
this.mutabilityPlan = domainJtd.getMutabilityPlan().isMutable()
|
||||
? new AttributeConverterMutabilityPlanImpl<>( attributeConverter )
|
||||
: ImmutableMutabilityPlan.INSTANCE;
|
||||
|
||||
log.debugf( "Created AttributeConverterTypeAdapter -> %s", name );
|
||||
|
||||
// throw new UnsupportedOperationException( );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,18 +72,42 @@ public class AttributeConverterTypeAdapter<T> extends AbstractSingleColumnStanda
|
|||
return name;
|
||||
}
|
||||
|
||||
public Class getModelType() {
|
||||
return modelType;
|
||||
public JavaTypeDescriptor<T> getDomainJtd() {
|
||||
return domainJtd;
|
||||
}
|
||||
|
||||
public Class getJdbcType() {
|
||||
return jdbcType;
|
||||
public JavaTypeDescriptor<?> getRelationalJtd() {
|
||||
return relationalJtd;
|
||||
}
|
||||
|
||||
public JpaAttributeConverter<? extends T,?> getAttributeConverter() {
|
||||
return attributeConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void nullSafeSet(
|
||||
CallableStatement st,
|
||||
Object value,
|
||||
String name,
|
||||
SharedSessionContractImplementor session) throws SQLException {
|
||||
final AttributeConverter converter = attributeConverter.getConverterBean().getBeanInstance();
|
||||
final Object converted = converter.convertToDatabaseColumn( value );
|
||||
super.nullSafeSet( st, converted, name, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
protected void nullSafeSet(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
|
||||
final AttributeConverter converter = attributeConverter.getConverterBean().getBeanInstance();
|
||||
final Object converted = converter.convertToDatabaseColumn( value );
|
||||
super.nullSafeSet( st, converted, index, options );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected MutabilityPlan<T> getMutabilityPlan() {
|
||||
return mutabilityPlan;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.type.descriptor.converter;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConvertedValueExtractor<O,R> implements ValueExtractor<O> {
|
||||
private static final Logger log = Logger.getLogger( ConvertedValueExtractor.class );
|
||||
|
||||
private final ValueExtractor<R> relationalExtractor;
|
||||
private final AttributeConverter<O,R> converter;
|
||||
|
||||
public ConvertedValueExtractor(
|
||||
ValueExtractor<R> relationalExtractor,
|
||||
AttributeConverter<O, R> converter) {
|
||||
this.relationalExtractor = relationalExtractor;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public O extract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return doConversion( relationalExtractor.extract( rs, paramIndex, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public O extract(CallableStatement statement, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return doConversion( relationalExtractor.extract( statement, paramIndex, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public O extract(CallableStatement statement, String paramName, WrapperOptions options) throws SQLException {
|
||||
return doConversion( relationalExtractor.extract( statement, paramName, options ) );
|
||||
}
|
||||
|
||||
private O doConversion(R extractedValue) {
|
||||
try {
|
||||
O convertedValue = converter.convertToEntityAttribute( extractedValue );
|
||||
log.debugf( "Converted value on extraction: %s -> %s", extractedValue, convertedValue );
|
||||
return convertedValue;
|
||||
}
|
||||
catch (PersistenceException pe) {
|
||||
throw pe;
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
throw new PersistenceException( "Error attempting to apply AttributeConverter", re );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,10 +5,15 @@
|
|||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.type.descriptor.java;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Character} handling.
|
||||
|
@ -25,6 +30,7 @@ public class CharacterTypeDescriptor extends AbstractTypeDescriptor<Character> i
|
|||
public String toString(Character value) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character fromString(String string) {
|
||||
if ( string.length() != 1 ) {
|
||||
|
|
|
@ -31,6 +31,12 @@ public class EnumJavaTypeDescriptor<T extends Enum<T>> extends AbstractTypeDescr
|
|||
@Override
|
||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) {
|
||||
if ( context.getEnumeratedType() != null && context.getEnumeratedType() == EnumType.STRING ) {
|
||||
if ( context.getColumnLength() == 1 ) {
|
||||
return context.isNationalized()
|
||||
? context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.NCHAR )
|
||||
: context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.CHAR );
|
||||
}
|
||||
|
||||
return context.isNationalized()
|
||||
? context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.NVARCHAR )
|
||||
: context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.VARCHAR );
|
||||
|
|
|
@ -54,4 +54,9 @@ public class JavaTypeDescriptorBasicAdaptor<T> extends AbstractTypeDescriptor<T>
|
|||
"Wrap strategy not known for this Java type : " + getJavaType().getName()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JavaTypeDescriptorBasicAdaptor(" + getJavaType().getName() + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
package org.hibernate.type.descriptor.sql;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Types#CHAR CHAR} handling.
|
||||
*
|
||||
|
@ -27,4 +30,9 @@ public class CharTypeDescriptor extends VarcharTypeDescriptor {
|
|||
public int getSqlType() {
|
||||
return Types.CHAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
return super.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqlTypeDescriptorIndicators {
|
||||
int NO_COLUMN_LENGTH = -1;
|
||||
|
||||
/**
|
||||
* Was nationalized character datatype requested for the given Java type?
|
||||
*
|
||||
|
@ -65,6 +67,13 @@ public interface SqlTypeDescriptorIndicators {
|
|||
return Types.BOOLEAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Useful for resolutions based on column length. E.g. choosing between a VARCHAR (String) and a CHAR(1) (Character/char)
|
||||
*/
|
||||
default long getColumnLength() {
|
||||
return NO_COLUMN_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the TypeConfiguration for access to various type-system registries.
|
||||
*/
|
||||
|
|
|
@ -46,5 +46,6 @@ public interface DynamicParameterizedType extends ParameterizedType {
|
|||
|
||||
String[] getColumns();
|
||||
|
||||
Long[] getColumnLengths();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ package org.hibernate.orm.test.metamodel.mapping;
|
|||
|
||||
import java.sql.Statement;
|
||||
import java.sql.Types;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
|
@ -25,6 +28,7 @@ import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
|||
import org.hibernate.metamodel.model.convert.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.hibernate.testing.hamcrest.CollectionMatchers;
|
||||
|
@ -40,6 +44,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
|||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
|
@ -60,9 +65,10 @@ public class SmokeTests {
|
|||
.getEntityDescriptor( SimpleEntity.class );
|
||||
|
||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||
assert Integer.class.equals( identifierMapping.getMappedTypeDescriptor()
|
||||
.getMappedJavaTypeDescriptor()
|
||||
.getJavaType() );
|
||||
assertThat(
|
||||
identifierMapping.getMappedTypeDescriptor().getMappedJavaTypeDescriptor().getJavaType(),
|
||||
sameInstance( Integer.class )
|
||||
);
|
||||
|
||||
{
|
||||
final ModelPart namePart = entityDescriptor.findSubPart( "name" );
|
||||
|
@ -105,6 +111,23 @@ public class SmokeTests {
|
|||
assertThat( attrMapping.getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode(), is( Types.VARCHAR ) );
|
||||
}
|
||||
|
||||
{
|
||||
final ModelPart part = entityDescriptor.findSubPart( "gender3" );
|
||||
assert part instanceof BasicValuedSingularAttributeMapping;
|
||||
final BasicValuedSingularAttributeMapping attrMapping = (BasicValuedSingularAttributeMapping) part;
|
||||
assert "mapping_simple_entity".equals( attrMapping.getContainingTableExpression() );
|
||||
assert "gender3".equals( attrMapping.getMappedColumnExpression() );
|
||||
|
||||
assertThat( attrMapping.getJavaTypeDescriptor().getJavaType(), equalTo( Gender.class ) );
|
||||
|
||||
final BasicValueConverter valueConverter = attrMapping.getValueConverter();
|
||||
assertThat( valueConverter, instanceOf( JpaAttributeConverter.class ) );
|
||||
assertThat( valueConverter.getDomainJavaDescriptor(), is( attrMapping.getJavaTypeDescriptor() ) );
|
||||
assertThat( valueConverter.getRelationalJavaDescriptor().getJavaType(), equalTo( Character.class ) );
|
||||
|
||||
assertThat( attrMapping.getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode(), is( Types.CHAR ) );
|
||||
}
|
||||
|
||||
{
|
||||
final ModelPart part = entityDescriptor.findSubPart( "component" );
|
||||
assert part instanceof EmbeddedAttributeMapping;
|
||||
|
@ -223,6 +246,7 @@ public class SmokeTests {
|
|||
private String name;
|
||||
private Gender gender;
|
||||
private Gender gender2;
|
||||
private Gender gender3;
|
||||
private Component component;
|
||||
|
||||
@Id
|
||||
|
@ -260,6 +284,16 @@ public class SmokeTests {
|
|||
this.gender2 = gender2;
|
||||
}
|
||||
|
||||
@Convert( converter = GenderConverter.class )
|
||||
@Column( length = 1 )
|
||||
public Gender getGender3() {
|
||||
return gender3;
|
||||
}
|
||||
|
||||
public void setGender3(Gender gender3) {
|
||||
this.gender3 = gender3;
|
||||
}
|
||||
|
||||
@Embedded
|
||||
public Component getComponent() {
|
||||
return component;
|
||||
|
@ -270,6 +304,35 @@ public class SmokeTests {
|
|||
}
|
||||
}
|
||||
|
||||
static class GenderConverter implements AttributeConverter<Gender,Character> {
|
||||
|
||||
@Override
|
||||
public Character convertToDatabaseColumn(Gender attribute) {
|
||||
if ( attribute == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( attribute == Gender.MALE ) {
|
||||
return 'M';
|
||||
}
|
||||
|
||||
return 'F';
|
||||
}
|
||||
|
||||
@Override
|
||||
public Gender convertToEntityAttribute(Character dbData) {
|
||||
if ( dbData == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( 'M' == dbData ) {
|
||||
return Gender.MALE;
|
||||
}
|
||||
|
||||
return Gender.FEMALE;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
static class SubComponent {
|
||||
private String subAttribute1;
|
||||
|
|
|
@ -6,51 +6,70 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.query.sql;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.sql.Types;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests;
|
||||
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.hibernate.testing.orm.domain.contacts.Contact;
|
||||
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.hamcrest.CustomMatcher;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel(
|
||||
standardModels = StandardDomainModel.CONTACTS
|
||||
standardModels = StandardDomainModel.GAMBIT
|
||||
)
|
||||
@SessionFactory
|
||||
public class NativeQueryScalarTests {
|
||||
public static final String STRING_VALUE = "a string value";
|
||||
public static final String URL_STRING = "http://hibernate.org";
|
||||
|
||||
@Test
|
||||
public void fullyImplicitTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final String sql = "select gender, first, last, id from contacts";
|
||||
final String sql = "select theString, theInteger, id from EntityOfBasics";
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( Object[].class ) );
|
||||
|
||||
final Object[] values = (Object[]) result;
|
||||
assertThat( values.length, is(4 ) );
|
||||
assertThat( values.length, is(3 ) );
|
||||
|
||||
assertThat( ( (Number) values[0] ).intValue(), is( Contact.Gender.OTHER.ordinal() ) );
|
||||
assertThat( values[1], is( "My First" ) );
|
||||
assertThat( values[2], is( "Contact" ) );
|
||||
assertThat( values[3], is( 1 ) );
|
||||
assertThat( values[ 0 ], is( STRING_VALUE ) );
|
||||
assertThat( values[ 1 ], is( 2 ) );
|
||||
assertThat( values[ 2 ], is( 1 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -58,71 +77,192 @@ public class NativeQueryScalarTests {
|
|||
public void explicitOrderTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final String sql = "select gender, first, last, id from contacts";
|
||||
final String sql = "select theString, theInteger, id from EntityOfBasics";
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
// notice the reverse order from the select clause
|
||||
query.addScalar( "id" );
|
||||
query.addScalar( "last" );
|
||||
query.addScalar( "first" );
|
||||
query.addScalar( "gender" );
|
||||
query.addScalar( "theInteger" );
|
||||
query.addScalar( "theString" );
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( Object[].class ) );
|
||||
|
||||
final Object[] values = (Object[]) result;
|
||||
assertThat( values.length, is(4 ) );
|
||||
assertThat( values.length, is(3 ) );
|
||||
|
||||
assertThat( values[0], is( 1 ) );
|
||||
assertThat( values[1], is( "Contact" ) );
|
||||
assertThat( values[2], is( "My First" ) );
|
||||
assertThat( ( (Number) values[3] ).intValue(), is( Contact.Gender.OTHER.ordinal() ) );
|
||||
assertThat( values[ 0 ], is( 1 ) );
|
||||
assertThat( values[ 1 ], is( 2 ) );
|
||||
assertThat( values[ 2 ], is( STRING_VALUE ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
// @FailureExpected( reason = "Explicit type support not working atm" )
|
||||
public void explicitEnumTypeTest(SessionFactoryScope scope) {
|
||||
final String sql = "select id, gender, ordinal_gender from EntityOfBasics";
|
||||
|
||||
// first, without explicit typing
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final String sql = "select gender, first, last, id from contacts";
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
// notice the reverse order from the select clause
|
||||
query.addScalar( "id" );
|
||||
query.addScalar( "last" );
|
||||
query.addScalar( "first" );
|
||||
query.addScalar( "gender", Contact.Gender.class );
|
||||
query.addScalar( "gender" );
|
||||
query.addScalar( "ordinal_gender" );
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( Object[].class ) );
|
||||
|
||||
final Object[] values = (Object[]) result;
|
||||
assertThat( values.length, is(4 ) );
|
||||
assertThat( values.length, is(3 ) );
|
||||
|
||||
assertThat( values[0], is( 1 ) );
|
||||
assertThat( values[1], is( "Contact" ) );
|
||||
assertThat( values[2], is( "My First" ) );
|
||||
assertThat( values[3], is( Contact.Gender.OTHER ) );
|
||||
assertThat( values[ 0 ], is( 1 ) );
|
||||
assertThat( values[ 1 ], is( "MALE" ) );
|
||||
assertThat( values[ 2 ], matchesOrdinal( EntityOfBasics.Gender.FEMALE ) );
|
||||
}
|
||||
);
|
||||
|
||||
// then using explicit typing
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
query.addScalar( "id" );
|
||||
query.addScalar( "gender", EntityOfBasics.Gender.class );
|
||||
query.addScalar( "ordinal_gender", EntityOfBasics.Gender.class );
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( Object[].class ) );
|
||||
|
||||
final Object[] values = (Object[]) result;
|
||||
assertThat( values.length, is(3 ) );
|
||||
|
||||
assertThat( values[ 0 ], is( 1 ) );
|
||||
assertThat( values[ 1 ], is( EntityOfBasics.Gender.MALE ) );
|
||||
assertThat( values[ 2 ], is( EntityOfBasics.Gender.FEMALE ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void explicitConversionTest(SessionFactoryScope scope) {
|
||||
final String sql = "select converted_gender from EntityOfBasics";
|
||||
|
||||
// Control
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( String.class ) );
|
||||
|
||||
assertThat( result, is( "O" ) );
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// Converter instance
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
query.addScalar(
|
||||
"converted_gender",
|
||||
Character.class,
|
||||
new EntityOfBasics.GenderConverter()
|
||||
);
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( EntityOfBasics.Gender.class ) );
|
||||
|
||||
assertThat( result, is( EntityOfBasics.Gender.OTHER ) );
|
||||
}
|
||||
);
|
||||
|
||||
// Converter class
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
query.addScalar(
|
||||
"converted_gender",
|
||||
Character.class,
|
||||
EntityOfBasics.GenderConverter.class
|
||||
);
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( EntityOfBasics.Gender.class ) );
|
||||
|
||||
assertThat( result, is( EntityOfBasics.Gender.OTHER ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private Matcher matchesOrdinal(Enum enumValue) {
|
||||
return new CustomMatcher<Object>( "Enum ordinal value" ) {
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
return ( (Number) item ).intValue() == enumValue.ordinal();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public void verifyModel(SessionFactoryScope scope) {
|
||||
final EntityMappingType entityDescriptor = scope.getSessionFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getEntityMappingType( EntityOfBasics.class );
|
||||
|
||||
final ModelPart part = entityDescriptor.findSubPart( "convertedGender", null );
|
||||
assertThat( part, instanceOf( BasicValuedSingularAttributeMapping.class ) );
|
||||
final BasicValuedSingularAttributeMapping attrMapping = (BasicValuedSingularAttributeMapping) part;
|
||||
|
||||
assertThat( attrMapping.getJavaTypeDescriptor().getJavaType(), equalTo( EntityOfBasics.Gender.class ) );
|
||||
|
||||
final BasicValueConverter valueConverter = attrMapping.getValueConverter();
|
||||
assertThat( valueConverter, instanceOf( JpaAttributeConverter.class ) );
|
||||
assertThat( valueConverter.getDomainJavaDescriptor(), is( attrMapping.getJavaTypeDescriptor() ) );
|
||||
assertThat( valueConverter.getRelationalJavaDescriptor().getJavaType(), equalTo( Character.class ) );
|
||||
|
||||
assertThat( attrMapping.getJdbcMapping().getSqlTypeDescriptor().getJdbcTypeCode(), is( Types.CHAR ) );
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void prepareData(SessionFactoryScope scope) {
|
||||
public void prepareData(SessionFactoryScope scope) throws MalformedURLException {
|
||||
final URL url = new URL( URL_STRING );
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.persist(
|
||||
new Contact(
|
||||
1,
|
||||
new Contact.Name( "My First", "Contact"),
|
||||
Contact.Gender.OTHER,
|
||||
LocalDate.of(1990,4,18)
|
||||
)
|
||||
final EntityOfBasics entityOfBasics = new EntityOfBasics( 1 );
|
||||
entityOfBasics.setTheString( STRING_VALUE );
|
||||
entityOfBasics.setTheInteger( 2 );
|
||||
entityOfBasics.setGender( EntityOfBasics.Gender.MALE );
|
||||
entityOfBasics.setOrdinalGender( EntityOfBasics.Gender.FEMALE );
|
||||
entityOfBasics.setConvertedGender( EntityOfBasics.Gender.OTHER );
|
||||
entityOfBasics.setTheUrl( url );
|
||||
entityOfBasics.setTheInstant( Instant.EPOCH );
|
||||
|
||||
session.persist( entityOfBasics );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final EntityOfBasics entity = session.get( EntityOfBasics.class, 1 );
|
||||
assertThat( entity, notNullValue() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -130,7 +270,7 @@ public class NativeQueryScalarTests {
|
|||
@AfterEach
|
||||
public void cleanUpData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> session.createQuery( "delete Contact" ).executeUpdate()
|
||||
session -> session.createQuery( "delete EntityOfBasics" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.testing.orm.domain.gambit;
|
|||
|
||||
import java.net.URL;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Types;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
|
@ -26,6 +27,8 @@ import javax.persistence.Id;
|
|||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.annotations.SqlTypeCode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -34,7 +37,8 @@ public class EntityOfBasics {
|
|||
|
||||
public enum Gender {
|
||||
MALE,
|
||||
FEMALE
|
||||
FEMALE,
|
||||
OTHER
|
||||
}
|
||||
|
||||
private Integer id;
|
||||
|
@ -60,6 +64,13 @@ public class EntityOfBasics {
|
|||
private ZonedDateTime theZonedDateTime;
|
||||
private OffsetDateTime theOffsetDateTime;
|
||||
|
||||
public EntityOfBasics() {
|
||||
}
|
||||
|
||||
public EntityOfBasics(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
|
@ -127,7 +138,8 @@ public class EntityOfBasics {
|
|||
}
|
||||
|
||||
@Convert( converter = GenderConverter.class )
|
||||
@Column(name = "converted_gender")
|
||||
@Column(name = "converted_gender", length = 1)
|
||||
@SqlTypeCode( Types.CHAR )
|
||||
public Gender getConvertedGender() {
|
||||
return convertedGender;
|
||||
}
|
||||
|
@ -244,6 +256,10 @@ public class EntityOfBasics {
|
|||
return null;
|
||||
}
|
||||
|
||||
if ( attribute == Gender.OTHER ) {
|
||||
return 'O';
|
||||
}
|
||||
|
||||
if ( attribute == Gender.MALE ) {
|
||||
return 'M';
|
||||
}
|
||||
|
@ -257,6 +273,10 @@ public class EntityOfBasics {
|
|||
return null;
|
||||
}
|
||||
|
||||
if ( 'O' == dbData ) {
|
||||
return Gender.OTHER;
|
||||
}
|
||||
|
||||
if ( 'M' == dbData ) {
|
||||
return Gender.MALE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue