Как я объяснил в этой статье , для отображения массива с помощью Hibernate требуется пользовательский тип.
Итак, если вы определили IntArrayType
следующим образом:
public class IntArrayType
extends AbstractSingleColumnStandardBasicType<int[]>
implements DynamicParameterizedType {
public IntArrayType() {
super(
ArraySqlTypeDescriptor.INSTANCE,
IntArrayTypeDescriptor.INSTANCE
);
}
public String getName() {
return "int-array";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
@Override
public void setParameterValues(Properties parameters) {
((IntArrayTypeDescriptor)
getJavaTypeDescriptor())
.setParameterValues(parameters);
}
}
Вам также нужно ArraySqlTypeDescriptor
:
public class ArraySqlTypeDescriptor
implements SqlTypeDescriptor {
public static final ArraySqlTypeDescriptor INSTANCE =
new ArraySqlTypeDescriptor();
@Override
public int getSqlType() {
return Types.ARRAY;
}
@Override
public boolean canBeRemapped() {
return true;
}
@Override
public <X> ValueBinder<X> getBinder(
JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this) {
@Override
protected void doBind(
PreparedStatement st,
X value,
int index,
WrapperOptions options
) throws SQLException {
AbstractArrayTypeDescriptor<Object> abstractArrayTypeDescriptor =
(AbstractArrayTypeDescriptor<Object>)
javaTypeDescriptor;
st.setArray(
index,
st.getConnection().createArrayOf(
abstractArrayTypeDescriptor.getSqlArrayType(),
abstractArrayTypeDescriptor.unwrap(
value,
Object[].class,
options
)
)
);
}
@Override
protected void doBind(
CallableStatement st,
X value,
String name,
WrapperOptions options
) throws SQLException {
throw new UnsupportedOperationException(
"Binding by name is not supported!"
);
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(
final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>(javaTypeDescriptor, this) {
@Override
protected X doExtract(
ResultSet rs,
String name,
WrapperOptions options
) throws SQLException {
return javaTypeDescriptor.wrap(
rs.getArray(name),
options
);
}
@Override
protected X doExtract(
CallableStatement statement,
int index,
WrapperOptions options
) throws SQLException {
return javaTypeDescriptor.wrap(
statement.getArray(index),
options
);
}
@Override
protected X doExtract(
CallableStatement statement,
String name,
WrapperOptions options
) throws SQLException {
return javaTypeDescriptor.wrap(
statement.getArray(name),
options
);
}
};
}
}
И IntArrayTypeDescriptor
:
public class IntArrayTypeDescriptor
extends AbstractArrayTypeDescriptor<int[]> {
public static final IntArrayTypeDescriptor INSTANCE =
new IntArrayTypeDescriptor();
public IntArrayTypeDescriptor() {
super( int[].class );
}
@Override
protected String getSqlArrayType() {
return "integer";
}
}
Основная часть обработки типов Java-to-JDBC включена в базовый класс AbstractArrayTypeDescriptor
:
public abstract class AbstractArrayTypeDescriptor<T>
extends AbstractTypeDescriptor<T>
implements DynamicParameterizedType {
private Class<T> arrayObjectClass;
@Override
public void setParameterValues(Properties parameters) {
arrayObjectClass = ( (ParameterType) parameters
.get( PARAMETER_TYPE ) )
.getReturnedClass();
}
public AbstractArrayTypeDescriptor(Class<T> arrayObjectClass) {
super(
arrayObjectClass,
(MutabilityPlan<T>) new MutableMutabilityPlan<Object>() {
@Override
protected T deepCopyNotNull(Object value) {
return ArrayUtil.deepCopy( value );
}
}
);
this.arrayObjectClass = arrayObjectClass;
}
@Override
public boolean areEqual(Object one, Object another) {
if ( one == another ) {
return true;
}
if ( one == null || another == null ) {
return false;
}
return ArrayUtil.isEquals( one, another );
}
@Override
public String toString(Object value) {
return Arrays.deepToString((Object[]) value);
}
@Override
public T fromString(String string) {
return ArrayUtil.fromString(
string,
arrayObjectClass
);
}
@SuppressWarnings({ "unchecked" })
@Override
public <X> X unwrap(
T value,
Class<X> type,
WrapperOptions options
) {
return (X) ArrayUtil.wrapArray( value );
}
@Override
public <X> T wrap(
X value,
WrapperOptions options
) {
if( value instanceof Array ) {
Array array = (Array) value;
try {
return ArrayUtil.unwrapArray(
(Object[]) array.getArray(),
arrayObjectClass
);
}
catch (SQLException e) {
throw new IllegalArgumentException( e );
}
}
return (T) value;
}
protected abstract String getSqlArrayType();
}
AbstractArrayTypeDescriptor
использует ArrayUtil для обработки логики глубокого копирования, развертывания и развертывания массива Java.
Теперь ваше отображение будет выглядеть так:
@Entity(name = "Event")
@Table(name = "event")
@TypeDef(
name = "int-array",
typeClass = IntArrayType.class
)
public static class Event
extends BaseEntity {
@Type( type = "int-array" )
@Column(
name = "sensor_values",
columnDefinition = "integer[]"
)
private int[] sensorValues;
//Getters and setters omitted for brevity
}