HHH-15872 Fix some issues with UDT column ordering

This commit is contained in:
Christian Beikov 2022-12-21 04:31:11 +01:00
parent d288962fc2
commit e19727e454
5 changed files with 299 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

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