json - JPA (EclipseLink) 自定义类型是否可行?

标签 json postgresql jpa jdbc eclipselink

特别是我对使用 PostgreSQLs json 类型感兴趣。

问题的核心似乎是Eclipselink中没有内部映射到json类型。因此,使用一种天真的方法:

@Column(name = "json", columnDefinition = "json")
public String getJson() {
    return json;
}

...并试图插入一个对象,我得到一个异常:

Internal Exception: org.postgresql.util.PSQLException: ERROR: column "json" is of type json but expression is of type character varying

我想很公平。

查看 EclipseLink 文档,似乎适用的自定义(转换映射、 native 查询、转换器)依赖于由支持的映射(数字、日期、字符串等)组成的数据,因此这使得这很尴尬绕过使用供应商特定类型。

这令人沮丧的主要原因是 posgresql 中的 json 类型与 text/varchar 表示相同,我相信(目前,但不是永远)只是该类型的别名- 因此驱动程序不仅能够传输它,它只是我的方式中的验证规则。

就解决方案而言,我不介意失去可移植性(在与数据库无关和使用供应商特定类型方面),但只想要一个允许我使用 json 类型的解决方案普通 JPA 实体的一个属性,并保留它习惯的所有其他行为(模式生成、合并、持久化、事务代码

最佳答案

遍历 SO 我发现了很多关于映射到 Postgres 的 JSON 或 XML 类型的问题。看起来没有人遇到过从自定义 Postgres 类型读取的问题,所以这里是使用纯 JPA 类型转换机制读取和写入的解决方案。

Postgres JDBC 驱动程序将未知(到 Java)类型的所有属性映射到 org.postgresql.util.PGobject 对象中,因此为该类型创建转换器就足够了。这是实体示例:

@Entity
public class Course extends AbstractEntity {
    @Column(name = "course_mapped", columnDefinition = "json")
    @Convert(converter = CourseMappedConverter.class)
    private CourseMapped courseMapped;  // have no idea why would you use String json instead of the object to map

    // getters and setters
}

这里是转换器示例:

@Converter
public class CourseMappedConverter implements AttributeConverter<CourseMapped, PGobject> {
    @Override
    public PGobject convertToDatabaseColumn(CourseMapped courseMapped) {
        try {
            PGobject po = new PGobject();
            // here we tell Postgres to use JSON as type to treat our json
            po.setType("json");
            // this is Jackson already added as dependency to project, it could be any JSON marshaller
            po.setValue((new ObjectMapper()).writeValueAsString(courseMapped));
            return po;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public CourseMapped convertToEntityAttribute(PGobject po) {
        try {
            return (new ObjectMapper()).readValue(po.getValue(),CourseMapped.class);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

如果你真的需要在你的实体中坚持使用 String JSON 表示,你可以为 String 类型制作这样的转换器

implements AttributeConverter<String, PGobject>

这是非常肮脏的(虽然有效)概念证明,它还使用假对象序列化告诉 JPA 对象已更改,如果它是的话

https://github.com/sasa7812/psql-cache-evict-POC

关于json - JPA (EclipseLink) 自定义类型是否可行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20339580/

相关文章:

javascript - d3 包布局中的 Json 格式问题

json - Play [Scala] : How to flatten a JSON object

ios - AFNetworking错误-'无效的JSON写入类型(NSConcreteData)'-上传音频文件时

java - 使用 JDBI 的 Postgres Integer[] 存储

postgresql - 如何使用从属 View 更改物化 View

java - 如何在 JPA 存储库之外定义存储过程

javascript - 在 AngularJS 中搜索 JSON 文件

postgresql:顺序执行多个查询并将结果发送到文件

java - 如何使用 JPA 在表末尾插入实体?

java - JPA聚合根方法