HHH-16125 fix the encoding of enum arrays to varbinary

This commit is contained in:
Gavin 2023-04-28 17:41:57 +02:00 committed by Gavin King
parent 9c6c3eba81
commit bfb0fc6aba
2 changed files with 43 additions and 14 deletions

View File

@ -303,13 +303,11 @@ public class ArrayJavaType<T> extends AbstractArrayJavaType<T[], T> {
return (X) value; return (X) value;
} }
else if ( type == byte[].class ) { else if ( type == byte[].class ) {
// byte[] can only be requested if the value should be serialized return (X) toBytes( value );
return (X) SerializationHelper.serialize( value );
} }
else if ( type == BinaryStream.class ) { else if ( type == BinaryStream.class ) {
// BinaryStream can only be requested if the value should be serialized
//noinspection unchecked //noinspection unchecked
return (X) new BinaryStreamImpl( SerializationHelper.serialize( value ) ); return (X) new BinaryStreamImpl( toBytes( value ) );
} }
else if ( type.isArray() ) { else if ( type.isArray() ) {
final Class<?> preferredJavaTypeClass = type.getComponentType(); final Class<?> preferredJavaTypeClass = type.getComponentType();
@ -360,19 +358,52 @@ public class ArrayJavaType<T> extends AbstractArrayJavaType<T[], T> {
return wrapped; return wrapped;
} }
else if ( value instanceof byte[] ) { else if ( value instanceof byte[] ) {
// When the value is a byte[], this is a deserialization request return fromBytes( (byte[]) value );
//noinspection unchecked
return (T[]) SerializationHelper.deserialize( (byte[]) value );
} }
else if ( value instanceof BinaryStream ) { else if ( value instanceof BinaryStream ) {
// When the value is a BinaryStream, this is a deserialization request // When the value is a BinaryStream, this is a deserialization request
//noinspection unchecked return fromBytes( ( (BinaryStream) value ).getBytes() );
return (T[]) SerializationHelper.deserialize( ( (BinaryStream) value ).getBytes() );
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
private static <T> byte[] toBytes(T[] value) {
if ( value.getClass().getComponentType().isEnum() ) {
final byte[] array = new byte[value.length];
for (int i = 0; i < value.length; i++ ) {
// encode null enum value as -1
array[i] = value[i] == null ? -1 : (byte) ((Enum<?>) value[i]).ordinal();
}
return array;
}
else {
// byte[] can only be requested if the value should be serialized
return SerializationHelper.serialize( value );
}
}
private T[] fromBytes(byte[] value) {
Class<T> elementClass = getElementJavaType().getJavaTypeClass();
byte[] bytes = value;
if ( elementClass.isEnum() ) {
final Object[] array = (Object[]) Array.newInstance( elementClass, bytes.length );
for (int i = 0; i < bytes.length; i++ ) {
// null enum value was encoded as -1
array[i] = bytes[i] == -1 ? null : elementClass.getEnumConstants()[bytes[i]];
}
//noinspection unchecked
return (T[]) array;
}
else {
// When the value is a byte[], this is a deserialization request
//noinspection unchecked
return (T[]) SerializationHelper.deserialize(value);
}
}
private static class ArrayMutabilityPlan<T> implements MutabilityPlan<T[]> { private static class ArrayMutabilityPlan<T> implements MutabilityPlan<T[]> {
private final Class<T> componentClass; private final Class<T> componentClass;

View File

@ -13,7 +13,6 @@ import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.internal.util.SerializationHelper;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
@ -146,12 +145,11 @@ public class EnumArrayTest extends BaseNonConfigCoreFunctionalTestCase {
return array; return array;
} }
else { else {
// We have to always serialize the Byte[] since it can contain nulls, but VARBINARY can't final byte[] array = new byte[enums.length];
final Byte[] array = new Byte[enums.length];
for ( int i = 0; i < enums.length; i++ ) { for ( int i = 0; i < enums.length; i++ ) {
array[i] = enums[i] == null ? null : (byte) enums[i].ordinal(); array[i] = enums[i] == null ? -1 : (byte) enums[i].ordinal();
} }
return SerializationHelper.serialize( array ); return array;
} }
} }