PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Sind JPA (EclipseLink) benutzerdefinierte Typen möglich?

Beim Durchlaufen von SO habe ich viele Fragen wie diese zu JSON- oder XML-Typen für die Zuordnung zu Postgres gefunden. Es sieht so aus, als ob noch niemand mit dem Problem des Lesens von benutzerdefinierten Postgres-Typen konfrontiert war, also hier die Lösung sowohl für das Lesen als auch für das Schreiben mit einem reinen JPA-Typkonvertierungsmechanismus.

Der Postgres-JDBC-Treiber ordnet alle Attribute für unbekannte (für Java) Typen dem Objekt org.postgresql.util.PGobject zu, sodass es ausreicht, einen Konverter für diesen Typ zu erstellen. Hier ist ein Entitätsbeispiel:

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

Hier das Konverter-Beispiel:

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

Wenn Sie sich in Ihrer Entität wirklich an die String-JSON-Darstellung halten müssen, können Sie einen Konverter wie diesen für den String-Typ erstellen

implements AttributeConverter<String, PGobject>

Hier ist ein sehr schmutziger (obwohl funktionierender) Proof of Concept, der auch eine gefälschte Objektserialisierung verwendet, um JPA mitzuteilen, dass das Objekt geändert wurde, falls dies der Fall war

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