Hibernate-reactive: Unterstützung für benutzerdefinierte Benutzertypen

Erstellt am 9. Juli 2020  ·  30Kommentare  ·  Quelle: hibernate/hibernate-reactive

Hallo an alle. Unterstützt Hibernate Reactive benutzerdefinierte Benutzertypen? Ich möchte Postgres JSONB Type verwenden und habe dafür die folgende Bibliothek https://github.com/vladmihalcea/hibernate-types verwendet, die ihre benutzerdefinierten Typen basierend auf Hibernates AbstractSingleColumnStandardBasicType erstellt . Leider sind die Spalten, die diese Typen verwenden, in den Entitäten immer null, wenn Sie von Hibernate zu Hibernate Reactive wechseln. Als Alternative habe ich diesen Artikel gefunden, der die JSONB Postgres-Unterstützung auf dem UserType des Hibernates

design

Alle 30 Kommentare

Hallo, ich habe UserType nicht getestet, da diese Schnittstelle eher an JDBC gebunden ist. (Obwohl es im Prinzip vielleicht so gemacht werden könnte, dass es meistens funktioniert.)

Stattdessen war meine Idee, dass die Leute JPA-Konverter verwenden könnten. Ich habe das getestet und AFAIK es funktioniert. Hast du das probiert?

Ich habe es mit einem Schnelltest mit UserType versucht und es scheint nicht zu funktionieren, da der PgClient beim Ausführen der Abfrage eine Ausnahme auslöst.

Ich habe es mit einem Schnelltest mit UserType versucht und es scheint nicht zu funktionieren, da der PgClient beim Ausführen der Abfrage eine Ausnahme auslöst.

Aber das könnte nur daran liegen, dass unsere gefälschte JDBC-Schicht unvollständig ist. (Einige nicht implementierte Methoden.)

Zur Verdeutlichung habe ich das Beispiel mit der vlad-Bibliothek ausprobiert:

    @TypeDefs({
            @TypeDef(name = "json", typeClass = JsonStringType.class),
            @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
    })
    @Entity(name="GuineaPig")
    @Table(name="Pig")
    public static class GuineaPig {
        <strong i="6">@Id</strong>
        private Integer id;
        private String name;

        @Type(type = "jsonb")
        @Column(columnDefinition = "jsonb")
        private  Location location;

Dies ist der Fehler:

Caused by: io.vertx.core.impl.NoStackTraceThrowable: Parameter at position[0] with class = [com.fasterxml.jackson.databind.node.ObjectNode] and value = [{"country":"UK","city":"Gotham"}] can not be coerced to the expected class = [java.lang.Object] for encoding.

Es scheint, dass der reaktive pg-Client einen anderen Typ verwendet, um in JSON zu konvertieren.

@gavinking Sollten wir eine Art von Zuordnung für die pg-Client-Typen unterstützen ?

JSON (io.reactiverse.pgclient.data.Json)
JSONB (io.reactiverse.pgclient.data.Json)
POINT (io.reactiverse.pgclient.data.Point)
LINE (io.reactiverse.pgclient.data.Line)
LSEG (io.reactiverse.pgclient.data.LineSegment)
BOX (io.reactiverse.pgclient.data.Box)
PATH (io.reactiverse.pgclient.data.Path)
POLYGON (io.reactiverse.pgclient.data.Polygon)
CIRCLE (io.reactiverse.pgclient.data.Circle)

Ich denke, der Client erwartet ein Objekt vom Typ io.reactiverse.pgclient.data.Json . Es scheint jedoch, dass wir mit UserType richtig umgehen

Genau das meinte ich in meinem Kommentar oben. Unsere JDBC-Adapter sind nicht einmal annähernd an einer vollständigen Implementierung von JDBC, und ich halte es für sehr wahrscheinlich, dass sie es nie sein werden. Insbesondere für „exotischere“ JDBC-Typen kann es ziemlich schwierig sein, sie der/von der Vert.x-API zuzuordnen.

Sollten wir eine Art von Zuordnung für die pg-Client-Typen unterstützen?

Nun, klar, wenn es einigermaßen einfach ist.

Aber wenn nicht, sollten wir bedenken, dass UserType hier vielleicht einfach nicht die richtige Abstraktion ist, und nach einem anderen Ansatz suchen.

Ich meine, in dem Maße, in dem vorhandene UserType s zum Laufen gebracht werden können, ohne etwas Schreckliches zu tun, dann lassen Sie uns sie zum Laufen bringen. Es wird die Migration erleichtern. Aber ich halte es für möglich, dass wir schnell an Grenzen stoßen, was dort wirklich möglich ist.

ich werde nachsehen

ich werde nachsehen

Als ersten Schritt sollten wir einen Test für ein völlig schlichtes UserType hinzufügen, das keine ausgefallenen Datenbanktypen verwendet, nur um zu überprüfen, ob das Grundkonzept funktioniert (ich verstehe nicht, warum es nicht sollte ).

@gavinking Nein, ich habe Konverter noch nicht getestet, da ich Hibernate zusammen mit der Hibernate Types-Bibliothek verwende. Aber der Vorschlag, Konverter zu verwenden, würde bedeuten, dass ich am Ende einen einfachen Postgres-Text/Varchar in die DB einfüge und keinen Postgres-JSONB-Typ.

@gavinking Nein, ich habe Konverter noch nicht getestet, da ich Hibernate zusammen mit der Hibernate Types-Bibliothek verwende. Aber der Vorschlag, Konverter zu verwenden, würde bedeuten, dass ich am Ende einen einfachen Postgres-Text/Varchar in die DB einfüge und keinen Postgres-JSONB-Typ.

Zur Klarstellung: Sind Sie besorgt darüber, welchen Typ Sie in Java oder in der Datenbank haben? Hier gibt es zwei verschiedene Dinge.

  • Eine ist, JSONB als Spaltentyp zu verwenden, aber im Prinzip hätte ich gedacht, dass die Treiber Strings transparent in diesen Typ konvertieren können. (Nicht sicher, ich habe es nie versucht.)
  • Die zweite Möglichkeit besteht darin, io.reactiverse.pgclient.data.Json als Java-Typ in Ihrem Modell zu verwenden. Das ist ein ganz anderes Problem und würde in der Tat eher etwas wie ein UserType erfordern.

@gavinking
Ich möchte den Postgres-Typ JSONB verwenden. Ich denke, es wird nicht direkt von Hibernate unterstützt. Deshalb habe ich mich auf diese https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/ verlassen . Oder zum Beispiel diese https://thorben-janssen.com/persist-postgresqls-jsonb-data-type-hibernate/, wo die Anleitung UserType verwendet.

Richtig, ich verstehe das, aber haben Sie versucht, etwas wirklich Einfaches zu tun, z. B. einfach ein Java- String einer Spalte vom Typ JSONB zuzuordnen? Wäre das gut genug, wenn es funktioniert?

@gavinking Nein, das habe ich noch nicht

OK, dann kann es sein, dass der Vert.x-Client diese Typkonvertierung bereits unterstützt, wir müssten es versuchen, aber selbst wenn dies nicht der Fall ist, denke ich, dass es wahrscheinlich sollte.

@DavideD wie ist der Status hier? Soll ich mir das mal genauer anschauen?

Ich wurde abgelenkt. Fühlen Sie sich frei, dies anzugehen, wenn Sie Zeit haben.

In #301 habe ich einen Test hinzugefügt, der zeigt, dass UserType im Personalwesen funktioniert, zumindest in dem Maße, in dem unsere Adapter PreparedStatement und ResultSet eine originalgetreue Implementierung von JDBC sind ( was nicht besonders groß ist).

@gavinking Sollten wir eine Art von Zuordnung für die pg-Client-Typen unterstützen ?

JSON (io.reactiverse.pgclient.data.Json)
JSONB (io.reactiverse.pgclient.data.Json)
POINT (io.reactiverse.pgclient.data.Point)
LINE (io.reactiverse.pgclient.data.Line)
LSEG (io.reactiverse.pgclient.data.LineSegment)
BOX (io.reactiverse.pgclient.data.Box)
PATH (io.reactiverse.pgclient.data.Path)
POLYGON (io.reactiverse.pgclient.data.Polygon)
CIRCLE (io.reactiverse.pgclient.data.Circle)

Die Frage lautet nun: Können wir getObject() und setObject() in unseren JDBC-Adaptern dazu bringen, diese Typen zu unterstützen, ohne eine harte Abhängigkeit vom PostgreSQL-Client zu erzeugen?

Wäre es möglich, so etwas zu haben:

@Type(type="passthrough")
Circle circle

Das macht keine Konvertierung, sondern übergibt den Wert einfach so, wie er ist?

Die Frage lautet nun: Können wir getObject() und setObject() in unseren JDBC-Adaptern dazu bringen, diese Typen zu unterstützen, ohne eine harte Abhängigkeit vom PostgreSQL-Client zu erzeugen?

Nun, ich habe dies versucht, und anscheinend müssen wir eigentlich nichts Besonderes tun, um io.vertx.core.json.JsonObject auf Postgres oder MySQL zu handhaben. Sie können einfach getObject() / setObject() von Ihrem UserType .

Das funktioniert:

public class Json implements UserType {

    <strong i="15">@Override</strong>
    public int[] sqlTypes() {
        return new int[] {Types.OTHER};
    }

    <strong i="16">@Override</strong>
    public Class returnedClass() {
        return JsonObject.class;
    }

    <strong i="17">@Override</strong>
    public boolean equals(Object x, Object y) throws HibernateException {
        return Objects.equals(x,y);
    }

    <strong i="18">@Override</strong>
    public int hashCode(Object x) throws HibernateException {
        return Objects.hashCode(x);
    }

    <strong i="19">@Override</strong>
    public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
        return rs.getObject(names[0]);
    }

    <strong i="20">@Override</strong>
    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
        if (value==null) {
            st.setNull(index, Types.OTHER);
        }
        else {
            st.setObject(index, value);
        }
    }

    ...
}

Wäre es möglich, so etwas zu haben:

@Type(type="passthrough")
Circle circle

Das macht keine Konvertierung, sondern übergibt den Wert einfach so, wie er ist?

Ja, das würde auch funktionieren.

Siehe 54434c94b3ff57261fd905abaeb25961b2ed285c.

Ich würde sagen, wir können dieses Thema schließen.

Was ist mit den anderen Typen, wie zum Beispiel io.reactiverse.pgclient.data.Circle ?

@akoufa , um Ihnen jetzt konkrete Antworten auf Ihre ursprünglichen Fragen zu geben:

Unterstützt Hibernate Reactive benutzerdefinierte UserTypes ?

Die Antwort ist ja!

Sie müssen sich jedoch bewusst sein, dass, obwohl wir etwas, das JDBC sehr ähnlich sieht, für Ihre UserType , unter dem Deckmantel keine JDBC-Verbindung vorhanden ist, sondern ein ganz anderer nicht blockierender Datenbank-Client. Manche Dinge werden also einfach nicht funktionieren.

Ich habe die folgende Bibliothek verwendet https://github.com/vladmihalcea/hibernate-types

Also ich denke, da musst du ziemlich realistisch sein. Die obige Bibliothek ist so geschrieben, dass sie mit JDBC funktioniert. Während einige ihrer UserType s möglicherweise funktionieren, funktionieren andere nicht.

Als Alternative habe ich diesen Artikel gefunden, der die JSONB Postgres-Unterstützung auf den UserType des Hibernates aufbaut.

Sehen Sie sich an, wie ich dies in der Testsuite implementiert habe. Die Grundidee ist, dass Sie ein Vert.x JsonObject an den Vert.x PostgreSQL- oder MySQL-Client übergeben müssen, indem Sie einfach setObject() aufrufen.

Was ist mit den anderen Typen, wie zum Beispiel io.reactiverse.pgclient.data.Circle ?

Sollte der gleiche Deal sein, habe ich aber nicht getestet.

Übrigens, io.reactiverse.pgclient.data ist tot. Es ist für eine frühere Version des Clients. Das ist nicht das, was Sie sich ansehen sollten.

Hier die aktuelle Typenliste:

https://vertx.io/docs/vertx-pg-client/java/#_postgresql_type_mapping

Ich verstehe das, aber haben Sie versucht, etwas wirklich Einfaches zu tun, z. B. einfach einen Java-String einer Spalte vom Typ JSONB zuzuordnen?

...

OK, dann kann es sein, dass der Vert.x-Client diese Typkonvertierung bereits unterstützt, wir müssten es versuchen, aber selbst wenn dies nicht der Fall ist, denke ich, dass es wahrscheinlich sollte.

Nach dem docs ich oben verbunden, funktionierts. Ich habe sogar getestet, eine ganze Zahl direkt in eine JSONB -types-Spalte zu schreiben, und es hat funktioniert.

Im Prinzip müssen Sie also nicht einmal mit JsonObject wenn Sie nicht wollen. (Es ist aber wahrscheinlich sauberer.)

Sicher, könnten Sie einen Test für einige der anderen spezifischen Typen hinzufügen? Wie Linie oder Kreis. Damit wir zeigen können, wie das Mapping aussieht

Hi!

Haben Sie eine Bibliothek wie https://github.com/vladmihalcea/hibernate-types gesehen , die Sie mit hibernate-reactive verwenden können?

Falls das noch nicht existiert, würde ich gerne etwas für mein Projekt bauen (mit quarkus). Ich verwende viele JSON-Spalten in Postgres.

Aber ich weiß nicht, ob ich es falsch verstehe, aber hibernate-reactive erlauben nur benutzerdefinierten Typ durch Implementieren von UserType Schnittstelle? (http://hibernate.org/reactive/documentation/1.0/reference/html_single/#_custom_types)

@AlexandreGuidin , ich glaube @gavinking hat deine Fragen bereits in einem der vorherigen Kommentare beantwortet: https://github.com/hibernate/hibernate-reactive/issues/279#issuecomment -666289449

Aber wenn ich etwas vermisse, können Sie gerne noch ein paar Fragen stellen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen