您需要创建自己的类型并实现
UserTypeinterface。根据下一个响应,我编写了一个泛型
UserType,可以在所有数组中使用,并且可以使用,但是您必须使用
非原始数据类型 (Integer,Long,String等)。否则,请参见上述
Boolean类型更新。
public class GenericArrayUserType<T extends Serializable> implements UserType { protected static final int[] SQL_TYPES = { Types.ARRAY }; private Class<T> typeParameterClass; @Override public Object assemble(Serializable cached, Object owner) throws HibernateException { return this.deepCopy(cached); } @Override public Object deepCopy(Object value) throws HibernateException { return value; } @SuppressWarnings("unchecked") @Override public Serializable disassemble(Object value) throws HibernateException { return (T) this.deepCopy(value); } @Override public boolean equals(Object x, Object y) throws HibernateException { if (x == null) { return y == null; } return x.equals(y); } @Override public int hashCode(Object x) throws HibernateException { return x.hashCode(); } @Override public boolean isMutable() { return true; } @Override public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException { if (resultSet.wasNull()) { return null; } if (resultSet.getArray(names[0]) == null) { return new Integer[0]; } Array array = resultSet.getArray(names[0]); @SuppressWarnings("unchecked") T javaArray = (T) array.getArray(); return javaArray; } @Override public void nullSafeSet(PreparedStatement statement, Object value, int index, SessionImplementor session) throws HibernateException, SQLException { Connection connection = statement.getConnection(); if (value == null) { statement.setNull(index, SQL_TYPES[0]); } else { @SuppressWarnings("unchecked") T castObject = (T) value; Array array = connection.createArrayOf("integer", (Object[]) castObject); statement.setArray(index, array); } } @Override public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } @Override public Class<T> returnedClass() { return typeParameterClass; } @Override public int[] sqlTypes() { return new int[] { Types.ARRAY }; }}然后,数组属性将是具有相同维的相同类型的数据库:
integer[]
->Integer[]
text[][]
->String[][]
在这种特殊情况下,将
GenericType类放在属性之上
@Type(type = "packageofclass.GenericArrayUserType")
那么您的实体将是:
@Entity@Table(name="sal_emp")public class SalEmp { @Id private String name; @Column(name="pay_by_quarter") @Type(type = "packageofclass.GenericArrayUserType") private Integer[] payByQuarter; @Column(name="schedule") @Type(type = "packageofclass.GenericArrayUserType") private String[][] schedule; //Getters, Setters, ToString, equals, and so on}如果您不想使用此泛型
UserType,请
Integer[]输入
String[][]类型。您需要编写自己的类型,在您的情况下,将如下所示:
整数[]
public class IntArrayUserType implements UserType {protected static final int[] SQL_TYPES = { Types.ARRAY };
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return this.deepCopy(cached);
}@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Integer[]) this.deepCopy(value);
}@Override
public boolean equals(Object x, Object y) throws HibernateException {if (x == null) { return y == null;}return x.equals(y);}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}@Override
public boolean isMutable() {
return true;
}@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
if (resultSet.wasNull()) {
return null;
}
if (resultSet.getArray(names[0]) == null) {
return new Integer[0];
}Array array = resultSet.getArray(names[0]);Integer[] javaArray = (Integer[]) array.getArray();return javaArray;
}
@Override
public void nullSafeSet(PreparedStatement statement, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
Connection connection = statement.getConnection();
if (value == null) {
statement.setNull(index, SQL_TYPES[0]);
} else {
Integer[] castObject = (Integer[]) value;
Array array = connection.createArrayOf(“integer”, castObject);
statement.setArray(index, array);
}
}@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}@Override
public ClassreturnedClass() {
return Integer[].class;
}@Override
public int[] sqlTypes() {
return new int[] { Types.ARRAY };
}
}文本[][]
public class StringMultidimensionalArrayType implements UserType {protected static final int[] SQL_TYPES = { Types.ARRAY };
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return this.deepCopy(cached);
}@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}@Override
public Serializable disassemble(Object value) throws HibernateException {
return (String[][]) this.deepCopy(value);
}@Override
public boolean equals(Object x, Object y) throws HibernateException {if (x == null) { return y == null;}return x.equals(y);}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}@Override
public boolean isMutable() {
return true;
}@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
if (resultSet.wasNull()) {
return null;
}
if (resultSet.getArray(names[0]) == null) {
return new String[0][];
}Array array = resultSet.getArray(names[0]);String[][] javaArray = (String[][]) array.getArray();return javaArray;
}
@Override
public void nullSafeSet(PreparedStatement statement, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
Connection connection = statement.getConnection();
if (value == null) {
statement.setNull(index, SQL_TYPES[0]);
} else {
String[][] castObject = (String[][]) value;
Array array = connection.createArrayOf(“integer”, castObject);
statement.setArray(index, array);
}
}@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}@Override
public ClassreturnedClass() {
return String[][].class;
}@Override
public int[] sqlTypes() {
return new int[] { Types.ARRAY };
}}
在这种情况下,您的媒体资源具有不同的类型:
@Column(name="pay_by_quarter")@Type(type = "packageofclass.IntArrayUserType")private Integer[] payByQuarter;@Column(name="schedule")@Type(type = "packageofclass.StringMultidimensionalArrayType")private String[][] schedule;
更新休眠用户类型
使用Boolean或boolean似乎无法使用
GenericArrayUserType,因此可以在类型的
CREATEDDL声明
boolean中创建解决方案
bytea:
CREATE TABLE sal_emp ( name text, pay_by_quarter integer[], schedule text[][], wow_boolean bytea );
而您的财产没有任何类型:
private boolean[][][] wowBoolean;
它解析没有任何非常好
Type或
Converter。输出:
wowBoolean=[[[true, false], [true, false]],[[true, true], [true, true]]])
更新@Converter
的JPA 2.1
我已经尝试使用
@ConverterJPA
2.1和
Eclipselink和选项
Hibernate。我只是这样尝试过
integer[](不是
text[][])
Converter(*我已将该属性更改为a,
List<Integer>但这并不重要):
@Converterpublic class ConverterListInteger implements AttributeConverter<List<Integer>, Array>{ @Override public Array convertToDatabaseColumn(List<Integer> attribute) { DataSource source = ApplicationContextHolder.getContext().getBean(DataSource.class); try { Connection conn = source.getConnection(); Array array = conn.createArrayOf("integer", attribute.toArray()); return array; } catch (SQLException e) { e.printStackTrace(); } return null; } @Override public List<Integer> convertToEntityAttribute(Array dbData) { List<Integer> list = new ArrayList<>(); try { for(Object object : (Object[]) dbData.getArray()){ list.add((Integer) object); } } catch (SQLException e) { e.printStackTrace(); } return list; }}然后,将转换器添加到实体的属性中:
@Convert(converter=ConverterListInteger.class)private List<Integer> pay_by_quarter;
因此,基于的解决方案
JPA specification不起作用。为什么?Hibernate不支持数据库数组(
java.sql.Array)。
然后我尝试使用Eclipselink(请参阅此处的配置方法),它可以工作,但并不总是…似乎有一个错误,它第一次运行良好,但是下次无法更新或查询此行。然后,只要我成功添加新行,但是之后就无法更新或查询。
结论
目前,似乎没有
JPA适当的供应商支持……只有解决方案
Hibernate
UserType可以正常使用,但仅适用于
Hibernate。



