Hibernate-reactive: Dukungan untuk Jenis Pengguna khusus

Dibuat pada 9 Jul 2020  ·  30Komentar  ·  Sumber: hibernate/hibernate-reactive

Halo semua. Apakah Hibernate Reactive mendukung UserTypes kustom? Saya ingin menggunakan Postgres JSONB Type dan untuk itu saya menggunakan perpustakaan berikut https://github.com/vladmihalcea/hibernate-types yang membangun tipe kustomnya berdasarkan AbstractSingleColumnStandardBasicType Hibernate. Sayangnya hanya berpindah dari Hibernate ke Hibernate Reactive kolom yang menggunakan tipe ini selalu null di entitas. Sebagai alternatif, saya menemukan artikel ini yang membangun dukungan Postgres JSONB pada Hibernate's UserType . Apakah ada batasan yang diketahui tentang mendefinisikan jenis kustom dan menggunakan Hibernate Reactive saat ini?

design

Semua 30 komentar

Hai, saya tidak menguji UserType karena antarmuka itu agak terkait dengan JDBC. (Meskipun pada prinsipnya, mungkin itu bisa dibuat untuk sebagian besar berfungsi.)

Sebaliknya, ide saya adalah bahwa orang dapat menggunakan konverter JPA. Saya sudah mengujinya dan AFAIK berhasil. Sudahkah Anda mencoba itu?

Saya mencoba dengan tes cepat menggunakan UserType dan sepertinya tidak berhasil karena PgClient melempar pengecualian saat menjalankan kueri.

Saya mencoba dengan tes cepat menggunakan UserType dan sepertinya tidak berhasil karena PgClient melempar pengecualian saat menjalankan kueri.

Tapi itu mungkin hanya karena lapisan JDBC palsu kita tidak lengkap. (Beberapa metode yang tidak diterapkan.)

Untuk memperjelas, saya sudah mencoba contoh menggunakan perpustakaan vlad:

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

Ini adalah kesalahannya:

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.

Tampaknya klien pg reaktif menggunakan tipe yang berbeda untuk mengonversi ke JSON.

@gavinking Haruskah kita mendukung semacam pemetaan untuk tipe pg-client ?

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)

Saya pikir klien mengharapkan objek bertipe io.reactiverse.pgclient.data.Json . Sepertinya kita menangani UserType dengan benar

Benar jadi itulah yang saya maksud dalam komentar saya di atas. Adaptor JDBC kami bahkan tidak mendekati implementasi lengkap JDBC, dan saya melihatnya sangat mungkin bahwa itu tidak akan pernah terjadi. Khususnya, untuk tipe JDBC yang lebih “eksotis”, mungkin cukup sulit untuk memetakannya ke/dari Vert.x API.

Haruskah kita mendukung semacam pemetaan untuk tipe pg-client?

Yah, tentu, jika itu cukup mudah dilakukan.

Tetapi jika tidak, kita harus mempertimbangkan bahwa mungkin UserType bukanlah abstraksi yang tepat di sini, dan mencari pendekatan yang berbeda.

Maksud saya, sejauh UserType s yang ada dapat dibuat berfungsi tanpa melakukan sesuatu yang mengerikan, maka tentu saja, mari kita buat mereka bekerja. Ini akan membuat migrasi lebih mudah. Tapi saya pikir mungkin saja kita akan segera mengalami keterbatasan tentang apa yang benar-benar mungkin di sana.

akan saya lihat

akan saya lihat

Sebagai langkah pertama, kita harus menambahkan tes untuk UserType vanila yang benar-benar polos yang tidak menggunakan tipe basis data mewah apa pun, hanya untuk memeriksa apakah konsep dasarnya berfungsi (saya tidak mengerti mengapa tidak ).

@gavinking Tidak, saya belum menguji Konverter karena saya menggunakan Hibernate bersama dengan pustaka Tipe Hibernasi. Tetapi saran untuk menggunakan konverter berarti bahwa pada akhirnya saya akan meletakkan Teks Postgres/Varchar biasa ke DB dan bukan tipe Postgres JSONB.

@gavinking Tidak, saya belum menguji Konverter karena saya menggunakan Hibernate bersama dengan pustaka Tipe Hibernasi. Tetapi saran untuk menggunakan konverter berarti bahwa pada akhirnya saya akan meletakkan Teks Postgres/Varchar biasa ke DB dan bukan tipe Postgres JSONB.

Untuk memperjelas: apakah Anda khawatir tentang tipe apa yang Anda miliki di Java atau di database? Ada dua hal yang berbeda di sini.

  • Salah satunya adalah menggunakan JSONB sebagai tipe kolom, tetapi pada prinsipnya saya akan berpikir bahwa driver dapat secara transparan mengonversi string ke tipe itu. (Tidak yakin, saya tidak pernah mencoba.)
  • Yang kedua adalah menggunakan io.reactiverse.pgclient.data.Json sebagai tipe Java dalam model Anda. Itu masalah yang sama sekali berbeda dan memang membutuhkan sesuatu yang lebih seperti UserType .

@gavinking
Saya ingin menggunakan tipe Postgres JSONB . Saya pikir itu tidak didukung langsung oleh Hibernate. Itu sebabnya saya mengandalkan ini https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/ . Atau misalnya ini https://thorben-janssen.com/persist-postgresqls-jsonb-data-type-hibernate/ di mana panduan ini menggunakan UserType .

Benar saya mengerti itu tetapi apakah Anda mencoba melakukan sesuatu yang sangat sederhana seperti hanya memetakan Java String ke kolom tipe JSONB ? Apakah itu cukup baik jika berhasil?

@gavinking Tidak, saya belum mencobanya. Ya itu akan cukup baik. Saya hanya perlu mengonversi objek JSON ke string JSON sebelum mencoba memasukkan Entitas saya ke dalam DB.

OK maka mungkin klien Vert.x sudah mendukung konversi jenis itu, kita perlu mencobanya, tetapi bahkan jika tidak, saya rasa saya pikir itu mungkin harus.

@DavideD apa statusnya di sini? Apakah Anda ingin saya melihat lebih dekat yang satu ini?

Aku teralihkan. Jangan ragu untuk menangani ini jika Anda punya waktu.

Di #301 saya telah menambahkan tes yang menunjukkan bahwa UserType s berfungsi di HR, setidaknya sejauh mana adaptor PreparedStatement dan ResultSet adalah implementasi setia JDBC ( yang tidak terlalu besar).

@gavinking Haruskah kita mendukung semacam pemetaan untuk tipe pg-client ?

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)

Jadi pertanyaannya sekarang adalah: dapatkah kita membuat getObject() dan setObject() di adaptor JDBC kita mendukung jenis ini tanpa membuat ketergantungan keras pada klien PostgreSQL?

Apakah mungkin untuk memiliki sesuatu seperti:

@Type(type="passthrough")
Circle circle

Itu tidak melakukan konversi apa pun tetapi hanya meneruskan nilai apa adanya?

Jadi pertanyaannya sekarang adalah: dapatkah kita membuat getObject() dan setObject() di adaptor JDBC kita mendukung jenis ini tanpa membuat ketergantungan keras pada klien PostgreSQL?

Yah, saya sudah mencoba ini, dan ternyata kita sebenarnya tidak perlu melakukan sesuatu yang khusus untuk menangani io.vertx.core.json.JsonObject di Postgres atau MySQL. Anda cukup menggunakan getObject() / setObject() dari UserType .

Ini bekerja:

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

    ...
}

Apakah mungkin untuk memiliki sesuatu seperti:

@Type(type="passthrough")
Circle circle

Itu tidak melakukan konversi apa pun tetapi hanya meneruskan nilai apa adanya?

Ya, itu juga akan berhasil.

Lihat 54434c94b3ff57261fd905abaeb25961b2ed285c.

Saya akan mengatakan kita bisa menutup masalah ini.

Bagaimana dengan tipe lain, seperti io.reactiverse.pgclient.data.Circle misalnya?

@akoufa sekarang untuk memberi Anda tanggapan konkret atas pertanyaan awal Anda:

Apakah Hibernate Reactive mendukung kustom UserTypes ?

Jawabannya iya!

Namun, Anda perlu menyadari bahwa meskipun kami mengekspos sesuatu yang sangat mirip JDBC ke UserType , di balik selimut tidak ada koneksi JDBC, tetapi klien basis data non-pemblokiran yang sama sekali berbeda. Jadi beberapa hal tidak akan berhasil.

Saya menggunakan perpustakaan berikut https://github.com/vladmihalcea/hibernate-types

Jadi saya pikir Anda harus cukup realistis tentang itu. Pustaka di atas ditulis untuk bekerja dengan JDBC, jadi sementara beberapa dari UserType mungkin berfungsi, yang lain tidak.

Sebagai alternatif, saya menemukan artikel ini yang membangun dukungan Postgres JSONB pada UserType Hibernate.

Lihatlah bagaimana saya menerapkan ini di test suite. Ide dasarnya adalah Anda harus meneruskan Vert.x JsonObject ke Vert.x PostgreSQL atau klien MySQL dengan hanya memanggil setObject() .

Bagaimana dengan tipe lain, seperti io.reactiverse.pgclient.data.Circle misalnya?

Harus kesepakatan yang sama, meskipun saya tidak menguji.

Omong-omong, io.reactiverse.pgclient.data sudah mati. Ini untuk versi klien sebelumnya. Bukan itu yang harus Anda lihat.

Berikut adalah daftar jenis saat ini:

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

Saya mengerti itu tetapi apakah Anda mencoba melakukan sesuatu yang sangat sederhana seperti hanya memetakan String Java ke kolom tipe JSONB?

...

OK maka mungkin klien Vert.x sudah mendukung konversi jenis itu, kita perlu mencobanya, tetapi bahkan jika tidak, saya rasa saya pikir itu mungkin harus.

Menurut dokumen I terkait di atas, ini tidak bekerja. Saya bahkan menguji menulis bilangan bulat langsung ke kolom JSONB -types dan berhasil.

Jadi pada prinsipnya Anda bahkan tidak perlu dipusingkan dengan JsonObject jika Anda tidak mau. (Ini mungkin lebih bersih.)

Tentu, dapatkah Anda menambahkan tes untuk beberapa jenis spesifik lainnya? Seperti garis atau lingkaran. Sehingga kami dapat menunjukkan seperti apa pemetaannya

Hai!

Pernahkah kalian melihat beberapa perpustakaan seperti https://github.com/vladmihalcea/hibernate-types untuk digunakan dengan hibernate-reactive ?

Jika itu belum ada, saya ingin membangun sesuatu untuk proyek saya (menggunakan quarkus). Saya menggunakan banyak kolom JSON di postgres.

Tetapi saya tidak tahu apakah saya salah, tetapi hibernate-reactive hanya mengizinkan jenis khusus dengan menerapkan dari antarmuka UserType ? (http://hibernate.org/reactive/documentation/1.0/reference/html_single/#_custom_types)

@AlexandreGuidin , saya pikir @gavinking sudah menjawab pertanyaan Anda di salah satu komentar sebelumnya: https://github.com/hibernate/hibernate-reactive/issues/279#issuecomment -666289449

Tetapi jika saya kehilangan sesuatu, jangan ragu untuk menindaklanjuti dengan beberapa pertanyaan lagi.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat