栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何使用Spring Data / JPA插入Postgres Array类型列中?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何使用Spring Data / JPA插入Postgres Array类型列中?

您需要创建自己的类型并实现

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 Class returnedClass() {
    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 Class returnedClass() {
    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

我已经尝试使用

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



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/428461.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号