Are JPA (EclipseLink) custom types possible?

后端 未结 2 1735
不知归路
不知归路 2020-12-08 06:20

In particular I am interested in using PostgreSQLs json type.

The core of the problem seems to be that there is no internal mapping in Eclipselink to <

2条回答
  •  天命终不由人
    2020-12-08 06:48

    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:

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

    Here the converter example:

    @Converter
    public class CourseMappedConverter implements AttributeConverter {
        @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
    

    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

提交回复
热议问题