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
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.
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.)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()
undsetObject()
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.