Are JPA (EclipseLink) custom types possible? Are JPA (EclipseLink) custom types possible? json json

Are JPA (EclipseLink) custom types possible?


Walking through SO I've found many questions like this regarding JSON or XML types for mapping into Postgres. It looks like nobody have faced the problem of reading from custom Postgres type, so here the solution for both reading and writing using pure JPA type conversion mechanism.

Postgres JDBC driver maps all attributes for unknown (to Java) types into org.postgresql.util.PGobject object, so it is enough to make converter for this type. Here is entity example:

@Entitypublic 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}

Here the converter example:

@Converterpublic 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;        }    }}

If you really need to stick to String JSON representation in your entity, you can make converter like this for String type

implements AttributeConverter<String, PGobject>

Here is very dirty (though working) proof of concept, it also uses fake object serialization to tell JPA that object was changed if it was

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


PostgreSQL is too strict about implicit casts between text-like types. The simplest way is a workaround by creating a cast; see this answer.

The clean way to do it would be to create a JPA provider extension that calls setObject(my_json), and/or teach your JPA provider to explicitly add CAST('myvalue' AS json) when it generates queries. This is a pain, as it requires JPA provider specific extensions.

This Stack Overflow search will find a bunch of related questions for the xml type, which people have similar problems with.