PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Les types personnalisés JPA (EclipseLink) sont-ils possibles ?

En parcourant SO, j'ai trouvé de nombreuses questions comme celle-ci concernant les types JSON ou XML pour le mappage dans Postgres. Il semble que personne n'ait rencontré le problème de la lecture à partir d'un type Postgres personnalisé, alors voici la solution pour la lecture et l'écriture en utilisant le mécanisme de conversion de type JPA pur.

Le pilote Postgres JDBC mappe tous les attributs des types inconnus (à Java) dans l'objet org.postgresql.util.PGobject, il suffit donc de créer un convertisseur pour ce type. Voici un exemple d'entité :

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

Voici l'exemple de convertisseur :

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

Si vous avez vraiment besoin de vous en tenir à la représentation String JSON dans votre entité, vous pouvez créer un convertisseur comme celui-ci pour le type String

implements AttributeConverter<String, PGobject>

Voici une preuve de concept très sale (bien que fonctionnelle), elle utilise également une fausse sérialisation d'objet pour indiquer à JPA que l'objet a été modifié s'il l'était

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