EclipseLink:PostgreSQL返回空列表作为text []的默认值?

时间:2018-08-06 11:50:03

标签: database postgresql jpa eclipselink postgresql-9.1

我将postgresql用作数据库,并通过JPA(Java持久性API)实现eclipselink在应用程序服务器(AS)端使用Java。

在postgres中,我有某些列使用text[]作为数据类型,这些列映射到AS端jpa对象中的List

JPA

    @Struct(name="label,.....")
    @Entity
    @Table(name="\"XYZ\"", schema="\"XYZ\"")
    @NamedQuery(name="XYZ.findAll", query="SELECT r FROM XYZ r")
    public class XYZ implements  Serializable {
        private static final long serialVersionUID = 1L;

        @Id
        @Column(name="\"resourceID\"")
        private String resourceID;

        @Array(databaseType = "text")
        @Column(name="\"label\"")
        private List<String> label;

.........
        // getter/setters 

}

因此,label在Postgres中存储为text[],并映射到JPA对象中的List<String>

当我将List值的JPA对象保存为null时,在检索JPA时,我会得到 Empty list 作为值,但从来没有 null strong>。

即使我保存时,为什么Postgres仍返回empty list作为默认值,所以仍将其设置为null。对于我的用例,empty listnull具有不同的语义。

String类型不会发生这种情况,那里不会给出空字符串。

text[]默认为空列表吗?

我找不到关于该问题的任何具体信息?

**编辑1:** 我尝试在JPA中将字段设置为String[],如下所示:

    @Struct(name="label,.....")
    @Entity
    @Table(name="\"XYZ\"", schema="\"XYZ\"")
    @NamedQuery(name="XYZ.findAll", query="SELECT r FROM XYZ r")
    public class XYZ implements  Serializable {
        private static final long serialVersionUID = 1L;

        @Id
        @Column(name="\"resourceID\"")
        private String resourceID;


        @Column(name="\"label\"")
        private String[] label;

.........
        // getter/setters 

}

运行时出现异常:

Stacktrace:

Caused by: org.postgresql.util.PSQLException: ERROR: column "label" is of type text[] but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.
  Position: 413
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:615)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:465)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:411)
    at org.jboss.jca.adapters.jdbc.CachedPreparedStatement.executeUpdate(CachedPreparedStatement.java:119)
    at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:493)

编辑2:

尝试使用答案中提到的ListToArrayConverter时,我在坚持的同时遇到了异常:

Internal Exception: org.postgresql.util.PSQLException: ERROR: column "label" is of type text[] but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.

1 个答案:

答案 0 :(得分:1)

EclipseLink就像处理ToMany关系一样处理List,因此始终使用空List对其进行初始化。可以在这里找到源代码:https://github.com/eclipse-ee4j/eclipselink

如果您不喜欢空白列表,而是想要null,则可以创建自己的转换器,例如:

@Converter(autoApply = true)
public class ListToArrayConveter implements AttributeConverter<List<String>, Object> {

    @Override
    public PostgreSQLTextArray convertToDatabaseColumn(List<String> attribute) {
        if (attribute == null || attribute.isEmpty()) {
            return null;
        }
        String[] rst = new String[attribute.size()];
        return new PostgreSQLTextArray(attribute.toArray(rst));
    }

    @Override
    public List<String> convertToEntityAttribute(Object dbData) {
            List<String> rst = new ArrayList<>();
        String[] elements = ((String[]) dbData);
        for (String element : elements) {
            rst.add(element);
        }
        if (list.isEmpty()) {
            return null;
        } else {
            return rst;
        }
    }
}