我尤其对使用PostgreSQLs json类型感兴趣。
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文档,似乎适用的自定义项(转换映射,本机查询,转换器)依赖于由受支持的映射(数字,日期,字符串等)组成的数据,因此这使使用它变得很尴尬供应商特定类型。
令人沮丧的主要原因是jsonposgresql 中的类型表示为与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