HHH-15872 Fix some issues with UDT column ordering
This commit is contained in:
parent
d288962fc2
commit
e19727e454
|
@ -57,6 +57,7 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
|
||||
private final String oracleTypeName;
|
||||
private final int[] orderMapping;
|
||||
private final int[] inverseOrderMapping;
|
||||
private final EmbeddableMappingType embeddableMappingType;
|
||||
private final ValueExtractor<Object[]> objectArrayExtractor;
|
||||
|
||||
|
@ -69,6 +70,16 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
this.embeddableMappingType = embeddableMappingType;
|
||||
this.oracleTypeName = typeName == null ? null : typeName.toUpperCase( Locale.ROOT );
|
||||
this.orderMapping = orderMapping;
|
||||
if ( orderMapping == null ) {
|
||||
this.inverseOrderMapping = null;
|
||||
}
|
||||
else {
|
||||
final int[] inverseOrderMapping = new int[orderMapping.length];
|
||||
for ( int i = 0; i < orderMapping.length; i++ ) {
|
||||
inverseOrderMapping[orderMapping[i]] = i;
|
||||
}
|
||||
this.inverseOrderMapping = inverseOrderMapping;
|
||||
}
|
||||
// We cache the extractor for Object[] here
|
||||
// since that is used in AggregateEmbeddableFetchImpl and AggregateEmbeddableResultImpl
|
||||
this.objectArrayExtractor = createBasicExtractor( new UnknownBasicJavaType<>( Object[].class ) );
|
||||
|
@ -128,6 +139,7 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
public Object createJdbcValue(Object domainValue, WrapperOptions options) throws SQLException {
|
||||
final Object[] jdbcValues = StructHelper.getJdbcValues(
|
||||
embeddableMappingType,
|
||||
orderMapping,
|
||||
embeddableMappingType.getValues( domainValue ),
|
||||
options
|
||||
);
|
||||
|
@ -141,7 +153,7 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
@Override
|
||||
public Object[] extractJdbcValues(Object rawJdbcValue, WrapperOptions options) throws SQLException {
|
||||
final Object[] attributes = ( (Struct) rawJdbcValue ).getAttributes();
|
||||
wrapRawJdbcValues( embeddableMappingType, orderMapping, attributes, 0, options );
|
||||
wrapRawJdbcValues( embeddableMappingType, orderMapping, inverseOrderMapping, attributes, 0, options );
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
@ -197,7 +209,7 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
final Object[] values = struct.getAttributes();
|
||||
final boolean jdbcRepresentation = getJavaType().getJavaTypeClass() == Object[].class;
|
||||
if ( jdbcRepresentation ) {
|
||||
wrapRawJdbcValues( embeddableMappingType, orderMapping, values, 0, options );
|
||||
wrapRawJdbcValues( embeddableMappingType, orderMapping, inverseOrderMapping, values, 0, options );
|
||||
//noinspection unchecked
|
||||
return (X) values;
|
||||
}
|
||||
|
@ -217,14 +229,14 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
};
|
||||
}
|
||||
|
||||
public static Object[] getAttributeValues(
|
||||
private static Object[] getAttributeValues(
|
||||
EmbeddableMappingType embeddableMappingType,
|
||||
int[] orderMapping,
|
||||
Object[] rawJdbcValues,
|
||||
WrapperOptions options) throws SQLException {
|
||||
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
||||
final Object[] attributeValues;
|
||||
if ( numberOfAttributeMappings != rawJdbcValues.length ) {
|
||||
if ( numberOfAttributeMappings != rawJdbcValues.length || orderMapping != null ) {
|
||||
attributeValues = new Object[numberOfAttributeMappings];
|
||||
}
|
||||
else {
|
||||
|
@ -232,12 +244,18 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
}
|
||||
int jdbcIndex = 0;
|
||||
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||
final int attributeIndex;
|
||||
if ( orderMapping == null ) {
|
||||
attributeIndex = i;
|
||||
}
|
||||
else {
|
||||
attributeIndex = orderMapping[i];
|
||||
}
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( attributeIndex );
|
||||
jdbcIndex += injectAttributeValue(
|
||||
attributeMapping,
|
||||
orderMapping,
|
||||
attributeValues,
|
||||
i,
|
||||
attributeIndex,
|
||||
rawJdbcValues,
|
||||
jdbcIndex,
|
||||
options
|
||||
|
@ -248,7 +266,6 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
|
||||
private static int injectAttributeValue(
|
||||
AttributeMapping attributeMapping,
|
||||
int[] orderMapping,
|
||||
Object[] attributeValues,
|
||||
int attributeIndex,
|
||||
Object[] rawJdbcValues,
|
||||
|
@ -256,13 +273,7 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
WrapperOptions options) throws SQLException {
|
||||
final MappingType mappedType = attributeMapping.getMappedType();
|
||||
final int jdbcValueCount;
|
||||
final Object rawJdbcValue;
|
||||
if ( orderMapping == null ) {
|
||||
rawJdbcValue = rawJdbcValues[jdbcIndex];
|
||||
}
|
||||
else {
|
||||
rawJdbcValue = rawJdbcValues[orderMapping[jdbcIndex]];
|
||||
}
|
||||
final Object rawJdbcValue = rawJdbcValues[jdbcIndex];
|
||||
if ( mappedType instanceof EmbeddableMappingType ) {
|
||||
final EmbeddableMappingType embeddableMappingType = (EmbeddableMappingType) mappedType;
|
||||
if ( embeddableMappingType.getAggregateMapping() != null ) {
|
||||
|
@ -300,7 +311,7 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
jdbcValueCount = embeddableMappingType.getJdbcValueCount();
|
||||
final Object[] jdbcValues = new Object[jdbcValueCount];
|
||||
System.arraycopy( rawJdbcValues, jdbcIndex, jdbcValues, 0, jdbcValues.length );
|
||||
final Object[] subValues = getAttributeValues( embeddableMappingType, orderMapping, jdbcValues, options );
|
||||
final Object[] subValues = getAttributeValues( embeddableMappingType, null, jdbcValues, options );
|
||||
attributeValues[attributeIndex] = embeddableMappingType.getRepresentationStrategy()
|
||||
.getInstantiator()
|
||||
.instantiate(
|
||||
|
@ -340,12 +351,26 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
private static int wrapRawJdbcValues(
|
||||
EmbeddableMappingType embeddableMappingType,
|
||||
int[] orderMapping,
|
||||
int[] inverseOrderMapping,
|
||||
Object[] jdbcValues,
|
||||
int jdbcIndex,
|
||||
WrapperOptions options) throws SQLException {
|
||||
final Object[] targetJdbcValues;
|
||||
if ( orderMapping == null ) {
|
||||
targetJdbcValues = jdbcValues;
|
||||
}
|
||||
else {
|
||||
targetJdbcValues = jdbcValues.clone();
|
||||
}
|
||||
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
||||
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||
final AttributeMapping attributeMapping;
|
||||
if ( orderMapping == null ) {
|
||||
attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||
}
|
||||
else {
|
||||
attributeMapping = embeddableMappingType.getAttributeMapping( orderMapping[i] );
|
||||
}
|
||||
final MappingType mappedType = attributeMapping.getMappedType();
|
||||
|
||||
if ( mappedType instanceof EmbeddableMappingType ) {
|
||||
|
@ -354,46 +379,37 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
|||
final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) embeddableType.getAggregateMapping()
|
||||
.getJdbcMapping()
|
||||
.getJdbcType();
|
||||
final Object rawJdbcValue;
|
||||
if ( orderMapping == null ) {
|
||||
rawJdbcValue = jdbcValues[jdbcIndex];
|
||||
}
|
||||
else {
|
||||
rawJdbcValue = jdbcValues[orderMapping[jdbcIndex]];
|
||||
}
|
||||
jdbcValues[jdbcIndex] = aggregateJdbcType.extractJdbcValues( rawJdbcValue, options );
|
||||
final Object rawJdbcValue = targetJdbcValues[jdbcIndex];
|
||||
targetJdbcValues[jdbcIndex] = aggregateJdbcType.extractJdbcValues( rawJdbcValue, options );
|
||||
jdbcIndex++;
|
||||
}
|
||||
else {
|
||||
jdbcIndex = wrapRawJdbcValues( embeddableType, orderMapping, jdbcValues, jdbcIndex, options );
|
||||
jdbcIndex = wrapRawJdbcValues( embeddableType, null, null, targetJdbcValues, jdbcIndex, options );
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert attributeMapping.getJdbcTypeCount() == 1;
|
||||
final Object rawJdbcValue;
|
||||
if ( orderMapping == null ) {
|
||||
rawJdbcValue = jdbcValues[jdbcIndex];
|
||||
}
|
||||
else {
|
||||
rawJdbcValue = jdbcValues[orderMapping[jdbcIndex]];
|
||||
}
|
||||
final Object rawJdbcValue = targetJdbcValues[jdbcIndex];
|
||||
if ( rawJdbcValue != null ) {
|
||||
final JdbcMapping jdbcMapping = attributeMapping.getJdbcMappings().get( 0 );
|
||||
switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) {
|
||||
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
||||
case SqlTypes.TIMESTAMP_UTC:
|
||||
// Only transform the raw jdbc value if it could be a TIMESTAMPTZ
|
||||
jdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType()
|
||||
targetJdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType()
|
||||
.wrap( transformRawJdbcValue( rawJdbcValue, options ), options );
|
||||
break;
|
||||
default:
|
||||
jdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType().wrap( rawJdbcValue, options );
|
||||
targetJdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType().wrap( rawJdbcValue, options );
|
||||
break;
|
||||
}
|
||||
}
|
||||
jdbcIndex++;
|
||||
}
|
||||
}
|
||||
if ( orderMapping != null ) {
|
||||
StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, targetJdbcValues, jdbcValues );
|
||||
}
|
||||
return jdbcIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.metamodel.mapping.AttributeMapping;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
|
@ -84,6 +85,7 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
}
|
||||
|
||||
private final int[] orderMapping;
|
||||
private final int[] inverseOrderMapping;
|
||||
private final EmbeddableMappingType embeddableMappingType;
|
||||
private final ValueExtractor<Object[]> objectArrayExtractor;
|
||||
|
||||
|
@ -96,6 +98,17 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
super( typeName, SqlTypes.STRUCT );
|
||||
this.embeddableMappingType = embeddableMappingType;
|
||||
this.orderMapping = orderMapping;
|
||||
if ( orderMapping == null ) {
|
||||
this.inverseOrderMapping = null;
|
||||
}
|
||||
else {
|
||||
final int[] inverseOrderMapping = new int[orderMapping.length];
|
||||
for ( int i = 0; i < orderMapping.length; i++ ) {
|
||||
inverseOrderMapping[orderMapping[i]] = i;
|
||||
}
|
||||
this.inverseOrderMapping = inverseOrderMapping;
|
||||
}
|
||||
// We cache the extractor for Obje
|
||||
// We cache the extractor for Object[] here
|
||||
// since that is used in AggregateEmbeddableFetchImpl and AggregateEmbeddableResultImpl
|
||||
this.objectArrayExtractor = super.getExtractor( new UnknownBasicJavaType<>( Object[].class ) );
|
||||
|
@ -170,13 +183,16 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
}
|
||||
assert end == string.length();
|
||||
if ( returnEmbeddable ) {
|
||||
final Object[] attributeValues = StructHelper.getAttributeValues( embeddableMappingType, array, options );
|
||||
final Object[] attributeValues = getAttributeValues( embeddableMappingType, array, options );
|
||||
//noinspection unchecked
|
||||
return (X) embeddableMappingType.getRepresentationStrategy().getInstantiator().instantiate(
|
||||
() -> attributeValues,
|
||||
options.getSessionFactory()
|
||||
);
|
||||
}
|
||||
else if ( inverseOrderMapping != null ) {
|
||||
StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, array.clone(), array );
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (X) array;
|
||||
}
|
||||
|
@ -282,8 +298,7 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
continue;
|
||||
}
|
||||
assert repeatsChar( string, i, 1 << quoteLevel, '"' );
|
||||
final JdbcMapping jdbcMapping = getJdbcValueSelectable( column )
|
||||
.getJdbcMapping();
|
||||
final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping();
|
||||
switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) {
|
||||
case SqlTypes.DATE:
|
||||
values[column] = fromRawObject(
|
||||
|
@ -396,8 +411,7 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
i += expectedQuotes - 1;
|
||||
if ( string.charAt( i + 1 ) == '(' ) {
|
||||
// This could be a nested struct
|
||||
final JdbcMapping jdbcMapping = getJdbcValueSelectable( column )
|
||||
.getJdbcMapping();
|
||||
final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping();
|
||||
if ( jdbcMapping.getJdbcType() instanceof PostgreSQLStructJdbcType ) {
|
||||
final PostgreSQLStructJdbcType structJdbcType;
|
||||
structJdbcType = (PostgreSQLStructJdbcType) jdbcMapping.getJdbcType();
|
||||
|
@ -411,7 +425,7 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
options
|
||||
);
|
||||
if ( returnEmbeddable ) {
|
||||
final Object[] attributeValues = StructHelper.getAttributeValues(
|
||||
final Object[] attributeValues = getAttributeValues(
|
||||
structJdbcType.embeddableMappingType,
|
||||
subValues,
|
||||
options
|
||||
|
@ -422,6 +436,14 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
values[column] = subValue;
|
||||
}
|
||||
else {
|
||||
if ( structJdbcType.inverseOrderMapping != null ) {
|
||||
StructHelper.orderJdbcValues(
|
||||
structJdbcType.embeddableMappingType,
|
||||
structJdbcType.inverseOrderMapping,
|
||||
subValues.clone(),
|
||||
subValues
|
||||
);
|
||||
}
|
||||
values[column] = subValues;
|
||||
}
|
||||
column++;
|
||||
|
@ -500,7 +522,36 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
|
||||
private SelectableMapping getJdbcValueSelectable(int jdbcValueSelectableIndex) {
|
||||
if ( orderMapping != null ) {
|
||||
jdbcValueSelectableIndex = orderMapping[jdbcValueSelectableIndex];
|
||||
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
||||
int count = 0;
|
||||
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( orderMapping[i] );
|
||||
final MappingType mappedType = attributeMapping.getMappedType();
|
||||
if ( mappedType instanceof EmbeddableMappingType ) {
|
||||
final EmbeddableMappingType embeddableMappingType = (EmbeddableMappingType) mappedType;
|
||||
final SelectableMapping aggregateMapping = embeddableMappingType.getAggregateMapping();
|
||||
if ( aggregateMapping == null ) {
|
||||
final SelectableMapping subSelectable = embeddableMappingType.getJdbcValueSelectable( jdbcValueSelectableIndex - count );
|
||||
if ( subSelectable != null ) {
|
||||
return subSelectable;
|
||||
}
|
||||
count += embeddableMappingType.getJdbcValueCount();
|
||||
}
|
||||
else {
|
||||
if ( count == jdbcValueSelectableIndex ) {
|
||||
return aggregateMapping;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( count == jdbcValueSelectableIndex ) {
|
||||
return (SelectableMapping) attributeMapping;
|
||||
}
|
||||
count += attributeMapping.getJdbcTypeCount();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return embeddableMappingType.getJdbcValueSelectable( jdbcValueSelectableIndex );
|
||||
}
|
||||
|
@ -602,6 +653,9 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
assert embeddableMappingType != null;
|
||||
final Object[] array = new Object[embeddableMappingType.getJdbcValueCount()];
|
||||
deserializeStruct( (String) rawJdbcValue, 0, 0, array, true, options );
|
||||
if ( inverseOrderMapping != null ) {
|
||||
StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, array.clone(), array );
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
@ -629,15 +683,24 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
char separator) {
|
||||
final int end = embeddableMappingType.getNumberOfAttributeMappings();
|
||||
for ( int i = 0; i < end; i++ ) {
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||
final AttributeMapping attributeMapping;
|
||||
final Object attributeValue;
|
||||
if ( orderMapping == null ) {
|
||||
attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||
attributeValue = array == null ? null : array[i];
|
||||
}
|
||||
else {
|
||||
attributeMapping = embeddableMappingType.getAttributeMapping( orderMapping[i] );
|
||||
attributeValue = array == null ? null : array[orderMapping[i]];
|
||||
}
|
||||
if ( attributeMapping instanceof BasicValuedMapping ) {
|
||||
appender.append( separator );
|
||||
separator = ',';
|
||||
if ( array == null || array[i] == null ) {
|
||||
if ( attributeValue == null ) {
|
||||
continue;
|
||||
}
|
||||
final JdbcMapping jdbcMapping = ( (BasicValuedMapping) attributeMapping ).getJdbcMapping();
|
||||
serializeBasicTo( appender, options, jdbcMapping, array[i] );
|
||||
serializeBasicTo( appender, options, jdbcMapping, attributeValue );
|
||||
}
|
||||
else if ( attributeMapping instanceof EmbeddedAttributeMapping ) {
|
||||
final EmbeddableMappingType mappingType = (EmbeddableMappingType) attributeMapping.getMappedType();
|
||||
|
@ -647,7 +710,7 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
appender,
|
||||
options,
|
||||
mappingType,
|
||||
array == null || array[i] == null ? null : mappingType.getValues( array[i] ),
|
||||
attributeValue == null ? null : mappingType.getValues( attributeValue ),
|
||||
separator
|
||||
);
|
||||
separator = ',';
|
||||
|
@ -655,13 +718,13 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
else {
|
||||
appender.append( separator );
|
||||
separator = ',';
|
||||
if ( array == null || array[i] == null ) {
|
||||
if ( attributeValue == null ) {
|
||||
continue;
|
||||
}
|
||||
appender.quoteStart();
|
||||
( (PostgreSQLStructJdbcType) aggregateMapping.getJdbcMapping().getJdbcType() ).serializeStructTo(
|
||||
appender,
|
||||
array[i],
|
||||
attributeValue,
|
||||
options
|
||||
);
|
||||
appender.quoteEnd();
|
||||
|
@ -767,6 +830,84 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
|||
}
|
||||
}
|
||||
|
||||
private Object[] getAttributeValues(
|
||||
EmbeddableMappingType embeddableMappingType,
|
||||
Object[] rawJdbcValues,
|
||||
WrapperOptions options) throws SQLException {
|
||||
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
||||
final Object[] attributeValues;
|
||||
if ( numberOfAttributeMappings != rawJdbcValues.length || orderMapping != null ) {
|
||||
attributeValues = new Object[numberOfAttributeMappings];
|
||||
}
|
||||
else {
|
||||
attributeValues = rawJdbcValues;
|
||||
}
|
||||
int jdbcIndex = 0;
|
||||
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
||||
final int attributeIndex;
|
||||
if ( orderMapping == null ) {
|
||||
attributeIndex = i;
|
||||
}
|
||||
else {
|
||||
attributeIndex = orderMapping[i];
|
||||
}
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( attributeIndex );
|
||||
jdbcIndex += injectAttributeValue(
|
||||
attributeMapping,
|
||||
attributeValues,
|
||||
attributeIndex,
|
||||
rawJdbcValues,
|
||||
jdbcIndex,
|
||||
options
|
||||
);
|
||||
}
|
||||
return attributeValues;
|
||||
}
|
||||
|
||||
private int injectAttributeValue(
|
||||
AttributeMapping attributeMapping,
|
||||
Object[] attributeValues,
|
||||
int attributeIndex,
|
||||
Object[] rawJdbcValues,
|
||||
int jdbcIndex,
|
||||
WrapperOptions options) throws SQLException {
|
||||
final MappingType mappedType = attributeMapping.getMappedType();
|
||||
final int jdbcValueCount;
|
||||
final Object rawJdbcValue = rawJdbcValues[jdbcIndex];
|
||||
if ( mappedType instanceof EmbeddableMappingType ) {
|
||||
final EmbeddableMappingType embeddableMappingType = (EmbeddableMappingType) mappedType;
|
||||
if ( embeddableMappingType.getAggregateMapping() != null ) {
|
||||
jdbcValueCount = 1;
|
||||
attributeValues[attributeIndex] = rawJdbcValue;
|
||||
}
|
||||
else {
|
||||
jdbcValueCount = embeddableMappingType.getJdbcValueCount();
|
||||
final Object[] subJdbcValues = new Object[jdbcValueCount];
|
||||
System.arraycopy( rawJdbcValues, jdbcIndex, subJdbcValues, 0, subJdbcValues.length );
|
||||
final Object[] subValues = getAttributeValues( embeddableMappingType, subJdbcValues, options );
|
||||
attributeValues[attributeIndex] = embeddableMappingType.getRepresentationStrategy()
|
||||
.getInstantiator()
|
||||
.instantiate(
|
||||
() -> subValues,
|
||||
embeddableMappingType.findContainingEntityMapping()
|
||||
.getEntityPersister()
|
||||
.getFactory()
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert attributeMapping.getJdbcTypeCount() == 1;
|
||||
jdbcValueCount = 1;
|
||||
final JdbcMapping jdbcMapping = attributeMapping.getJdbcMappings().get( 0 );
|
||||
final Object jdbcValue = jdbcMapping.getJdbcJavaType().wrap(
|
||||
rawJdbcValue,
|
||||
options
|
||||
);
|
||||
attributeValues[attributeIndex] = jdbcMapping.convertToDomainValue( jdbcValue );
|
||||
}
|
||||
return jdbcValueCount;
|
||||
}
|
||||
|
||||
private void appendTemporal(SqlAppender appender, JdbcMapping jdbcMapping, Object value, WrapperOptions options) {
|
||||
final TimeZone jdbcTimeZone = getJdbcTimeZone( options );
|
||||
//noinspection unchecked
|
||||
|
|
|
@ -90,11 +90,12 @@ public class StructHelper {
|
|||
|
||||
public static Object[] getJdbcValues(
|
||||
EmbeddableMappingType embeddableMappingType,
|
||||
int[] orderMapping,
|
||||
Object[] attributeValues,
|
||||
WrapperOptions options) throws SQLException {
|
||||
final int jdbcValueCount = embeddableMappingType.getJdbcValueCount();
|
||||
final Object[] jdbcValues;
|
||||
if ( jdbcValueCount != attributeValues.length ) {
|
||||
if ( jdbcValueCount != attributeValues.length || orderMapping != null ) {
|
||||
jdbcValues = new Object[jdbcValueCount];
|
||||
}
|
||||
else {
|
||||
|
@ -102,11 +103,17 @@ public class StructHelper {
|
|||
}
|
||||
int jdbcIndex = 0;
|
||||
for ( int i = 0; i < attributeValues.length; i++ ) {
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||
final int attributeIndex;
|
||||
if ( orderMapping == null ) {
|
||||
attributeIndex = i;
|
||||
}
|
||||
else {
|
||||
attributeIndex = orderMapping[i];
|
||||
}
|
||||
jdbcIndex += injectJdbcValue(
|
||||
attributeMapping,
|
||||
embeddableMappingType.getAttributeMapping( attributeIndex ),
|
||||
attributeValues,
|
||||
i,
|
||||
attributeIndex,
|
||||
jdbcValues,
|
||||
jdbcIndex,
|
||||
options
|
||||
|
@ -185,4 +192,52 @@ public class StructHelper {
|
|||
}
|
||||
return jdbcValueCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The <code>sourceJdbcValues</code> array is ordered according to the expected physical order,
|
||||
* as given through the argument order of @Instantiator.
|
||||
* The <code>targetJdbcValues</code> array should be ordered according to the Hibernate internal ordering,
|
||||
* which is based on property name.
|
||||
* This method copies from <code>sourceJdbcValues</code> to <code>targetJdbcValues</code> according to the ordering.
|
||||
*/
|
||||
public static void orderJdbcValues(
|
||||
EmbeddableMappingType embeddableMappingType,
|
||||
int[] inverseMapping,
|
||||
Object[] sourceJdbcValues,
|
||||
Object[] targetJdbcValues) {
|
||||
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
||||
int targetJdbcOffset = 0;
|
||||
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||
final MappingType mappedType = attributeMapping.getMappedType();
|
||||
final int jdbcValueCount = getJdbcValueCount( mappedType );
|
||||
|
||||
final int attributeIndex = inverseMapping[i];
|
||||
int sourceJdbcIndex = 0;
|
||||
for ( int j = 0; j < attributeIndex; j++ ) {
|
||||
sourceJdbcIndex += getJdbcValueCount( embeddableMappingType.getAttributeMapping( j ).getMappedType() );
|
||||
}
|
||||
|
||||
for ( int j = 0; j < jdbcValueCount; j++ ) {
|
||||
targetJdbcValues[targetJdbcOffset++] = sourceJdbcValues[sourceJdbcIndex + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getJdbcValueCount(MappingType mappedType) {
|
||||
final int jdbcValueCount;
|
||||
if ( mappedType instanceof EmbeddableMappingType ) {
|
||||
final EmbeddableMappingType subMappingType = (EmbeddableMappingType) mappedType;
|
||||
if ( subMappingType.getAggregateMapping() != null ) {
|
||||
jdbcValueCount = 1;
|
||||
}
|
||||
else {
|
||||
jdbcValueCount = subMappingType.getJdbcValueCount();
|
||||
}
|
||||
}
|
||||
else {
|
||||
jdbcValueCount = 1;
|
||||
}
|
||||
return jdbcValueCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,7 +266,7 @@ public class UserDefinedType implements Serializable, ContributableDatabaseObjec
|
|||
orderMapping = new int[columns.size()];
|
||||
int i = 0;
|
||||
for ( Column column : this.columns.values() ) {
|
||||
orderMapping[i++] = columns.indexOf( column );
|
||||
orderMapping[columns.indexOf( column )] = i++;
|
||||
}
|
||||
this.columns.clear();
|
||||
for ( Column column : columns ) {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class EmbeddableHelper {
|
||||
public static int[] determinePropertyMappingIndex(String[] propertyNames, String[] componentNames) {
|
||||
final int[] index = new int[propertyNames.length];
|
||||
int i = 0;
|
||||
for ( String componentName : componentNames ) {
|
||||
final int mappingIndex = Arrays.binarySearch( propertyNames, componentName );
|
||||
if ( mappingIndex != -1 ) {
|
||||
index[i++] = mappingIndex;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
public static boolean resolveIndex(String[] sortedComponentNames, String[] componentNames, int[] index) {
|
||||
boolean hasGaps = false;
|
||||
for ( int i = 0; i < componentNames.length; i++ ) {
|
||||
final int newIndex = Arrays.binarySearch( sortedComponentNames, componentNames[i] );
|
||||
index[i] = newIndex;
|
||||
hasGaps = hasGaps || newIndex < 0;
|
||||
}
|
||||
|
||||
return hasGaps;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue