Hibernate-reactive: دعم لأنواع المستخدم المخصصة

تم إنشاؤها على ٩ يوليو ٢٠٢٠  ·  30تعليقات  ·  مصدر: hibernate/hibernate-reactive

مرحبا بالجميع. هل يدعم وضع الإسبات التفاعلي أنواع UserTypes المخصصة؟ أريد استخدام Postgres JSONB Type ولهذا كنت أستخدم المكتبة التالية https://github.com/vladmihalcea/hibernate-types التي تبني أنواعها المخصصة بناءً على AbstractSingleColumnStandardBasicType في Hibernate. لسوء الحظ ، مجرد الانتقال من Hibernate إلى Hibernate Reactive تكون الأعمدة التي تستخدم هذه الأنواع فارغة دائمًا في الكيانات. وكبديل لذلك وجدت هذه المادة التي يبني انها الدعم JSONB بوستجرس على السبات في نوع المستخدم . هل هناك أي قيود معروفة حول تحديد الأنواع المخصصة واستخدام Hibernate Reactive في الوقت الحالي؟

design

ال 30 كومينتر

مرحبًا ، لم أختبر UserType لأن هذه الواجهة مرتبطة إلى حد ما بـ JDBC. (على الرغم من أنه من حيث المبدأ ، ربما يمكن جعله يعمل في الغالب).

بدلاً من ذلك ، كانت فكرتي أنه يمكن للأشخاص استخدام محولات JPA. لقد اختبرت ذلك و AFAIK يعمل. هل جربت ذلك؟

لقد حاولت باستخدام اختبار سريع باستخدام UserType ويبدو أنه لا يعمل لأن PgClient يطرح استثناءً عند تشغيل الاستعلام.

لقد حاولت باستخدام اختبار سريع باستخدام UserType ويبدو أنه لا يعمل لأن PgClient يطرح استثناءً عند تشغيل الاستعلام.

ولكن قد يكون ذلك بسبب أن طبقة JDBC المزيفة لدينا غير مكتملة. (بعض الأساليب غير المطبقة).

للتوضيح ، جربت المثال باستخدام مكتبة فلاد:

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

هذا هو الخطأ:

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.

يبدو أن عميل pg التفاعلي يستخدم نوعًا مختلفًا للتحويل إلى JSON.

gavinking هل يجب أن ندعم نوعًا من التعيين لأنواع عميل pg ؟

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)

أعتقد أن العميل يتوقع كائنًا من النوع io.reactiverse.pgclient.data.Json . يبدو أننا نتعامل مع UserType بشكل صحيح

صحيح ، هذا ما قصدته في تعليقي أعلاه. محولات JDBC الخاصة بنا ليست قريبة من التنفيذ الكامل لـ JDBC ، وأرى أنه من المحتمل جدًا أنها لن تكون كذلك. على وجه الخصوص ، بالنسبة لأنواع JDBC "الغريبة" ، قد يكون من الصعب جدًا تعيينها إلى / من Vert.x API.

هل يجب أن ندعم نوعًا من التعيين لأنواع عملاء pg؟

حسنًا ، بالتأكيد ، إذا كان من السهل القيام بذلك بشكل معقول.

ولكن إذا لم يكن الأمر كذلك ، فيجب أن نعتبر أنه ربما UserType ليس مجرد فكرة مجردة صحيحة هنا ، ونبحث عن نهج مختلف.

أعني ، إلى الحد الذي يمكن فيه جعل UserType s الحالية تعمل دون القيام بأي شيء فظيع ، ثم بالتأكيد ، دعونا نجعلها تعمل. سيجعل الهجرة أسهل. لكنني أعتقد أنه من الممكن أن نواجه بسرعة قيودًا على ما هو ممكن حقًا هناك.

سألقي نظرة

سألقي نظرة

كخطوة أولى ، يجب أن نضيف اختبارًا لقيمة بسيطة تمامًا UserType لا تستخدم أي أنواع قواعد بيانات خيالية ، فقط للتحقق من أن المفهوم الأساسي يعمل (لا أرى سبب عدم استخدامه ).

gavinking لا لم

gavinking لا لم

للتوضيح: هل أنت قلق بشأن أي نوع لديك في Java أو في قاعدة البيانات؟ هناك شيئان مختلفان هنا.

  • الأول هو استخدام JSONB كنوع العمود ، لكن من حيث المبدأ كنت أعتقد أن برامج التشغيل يمكنها تحويل السلاسل إلى هذا النوع بشفافية. (لست متأكدًا ، لم أحاول أبدًا).
  • والثاني هو استخدام io.reactiverse.pgclient.data.Json كنوع Java في نموذجك. هذه مشكلة مختلفة تمامًا وستتطلب بالفعل شيئًا يشبه UserType .

تضمين التغريدة
أريد استخدام نوع Postgres JSONB . أعتقد أنه لا يدعمه Hibernate مباشرة. لهذا السبب اعتمدت على هذا https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/ . أو على سبيل المثال https://thorben-janssen.com/persist-postgresqls-jsonb-data-type-hibernate/ حيث يستخدم الدليل UserType.

صحيح أنني أفهم ذلك ولكن هل حاولت القيام بشيء بسيط حقًا مثل تعيين Java String إلى عمود من النوع JSONB ؟ هل سيكون ذلك جيدًا بما يكفي إذا نجح؟

gavinking لا لم أحاول ذلك بعد. نعم ستكون جيدة بما فيه الكفاية. سأحتاج فقط إلى تحويل كائنات JSON إلى سلسلة JSON قبل محاولة إدراج الكيانات الخاصة بي في قاعدة البيانات.

حسنًا ، فقد يكون عميل Vert.x يدعم بالفعل هذا النوع من التحويل ، فسنحتاج إلى تجربته ، ولكن حتى لو لم يكن كذلك ، أعتقد أنه من المحتمل أن يكون كذلك.

DavideD ما هو الوضع هنا؟ هل تريد مني إلقاء نظرة فاحصة على هذا؟

لقد انحرفت عن مسارها. لا تتردد في معالجة هذا إذا كان لديك الوقت.

في # 301 ، أضفت اختبارًا يوضح أن UserType s يعمل في الموارد البشرية ، على الأقل إلى الحد الذي تكون فيه محولاتنا PreparedStatement و ResultSet تنفيذًا أمينًا لـ JDBC ( وهو ليس بدرجة كبيرة بشكل خاص).

gavinking هل يجب أن ندعم نوعًا من التعيين لأنواع عميل pg ؟

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)

لذا يصبح السؤال الآن: هل يمكننا جعل getObject() و setObject() في محولات JDBC الخاصة بنا تدعم هذه الأنواع دون إنشاء تبعية قوية لعميل PostgreSQL؟

هل من الممكن أن يكون لديك شيء مثل:

@Type(type="passthrough")
Circle circle

هذا لا يؤدي إلى أي تحويل ولكن فقط تمرير القيمة كما هي؟

لذا يصبح السؤال الآن: هل يمكننا جعل getObject() و setObject() في محولات JDBC الخاصة بنا تدعم هذه الأنواع دون إنشاء تبعية قوية لعميل PostgreSQL؟

حسنًا ، لقد جربت هذا ، ومن الواضح أننا لسنا بحاجة فعلاً إلى القيام بأي شيء خاص من أجل التعامل مع io.vertx.core.json.JsonObject على Postgres أو MySQL. يمكنك فقط استخدام getObject() / setObject() من UserType .

هذا يعمل:

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

    ...
}

هل من الممكن أن يكون لديك شيء مثل:

@Type(type="passthrough")
Circle circle

هذا لا يؤدي إلى أي تحويل ولكن فقط تمرير القيمة كما هي؟

نعم ، هذا سيعمل أيضًا.

انظر 54434c94b3ff57261fd905abaeb25961b2ed285c.

أود أن أقول أنه يمكننا إغلاق هذه المسألة.

ماذا عن الأنواع الأخرى ، مثل io.reactiverse.pgclient.data.Circle على سبيل المثال؟

akoufa الآن لأعطيك إجابات محددة على أسئلتك الأصلية:

هل يدعم رد الفعل الإسبات UserTypes المخصص؟

الجواب نعم!

ومع ذلك ، يجب أن تدرك أنه على الرغم من أننا نكشف شيئًا يشبه إلى حد كبير JDBC إلى UserType الخاص بك ، إلا أنه لا يوجد اتصال JDBC تحت الأغلفة ، ولكن يوجد عميل قاعدة بيانات مختلف تمامًا غير محظور. لذا فإن بعض الأشياء ببساطة لن تعمل.

كنت أستخدم المكتبة التالية https://github.com/vladmihalcea/hibernate-types

لذلك أعتقد أنك ستحتاج إلى أن تكون واقعيًا جدًا بشأن ذلك. تمت كتابة المكتبة أعلاه للعمل مع JDBC ، لذلك في حين أن بعضًا من UserType s قد يعمل ، فإن البعض الآخر لن يعمل.

كبديل ، وجدت هذه المقالة التي تبني دعم JSONB Postgres على Hibernate UserType .

ألق نظرة على كيفية تنفيذ هذا في مجموعة الاختبار. الفكرة الأساسية هي أنك تحتاج إلى تمرير Vert.x JsonObject إلى Vert.x PostgreSQL أو عميل MySQL عن طريق استدعاء setObject() .

ماذا عن الأنواع الأخرى ، مثل io.reactiverse.pgclient.data.Circle على سبيل المثال؟

يجب أن تكون نفس الصفقة ، على الرغم من أنني لم أختبر.

بالمناسبة ، io.reactiverse.pgclient.data مات. إنه لإصدار سابق من العميل. هذا ليس ما يجب أن تنظر إليه.

فيما يلي قائمة الأنواع الحالية:

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

أفهم ذلك ولكن هل حاولت فعل شيء بسيط حقًا مثل مجرد تعيين سلسلة Java إلى عمود من النوع JSONB؟

...

حسنًا ، فقد يكون عميل Vert.x يدعم بالفعل هذا النوع من التحويل ، فسنحتاج إلى تجربته ، ولكن حتى لو لم يكن كذلك ، أعتقد أنه من المحتمل أن يكون كذلك.

وفقا لمستندات أنا مرتبطة أعلاه، هذا لا يعمل. حتى أنني اختبرت كتابة عدد صحيح مباشرة إلى عمود من الأنواع JSONB نجح الأمر.

لذلك من حيث المبدأ ، لا تحتاج حتى إلى العبث بـ JsonObject إذا كنت لا تريد ذلك. (ربما يكون أكثر نظافة.)

بالتأكيد ، هل يمكنك إضافة اختبار لبعض الأنواع المحددة الأخرى؟ مثل خط أو دائرة. حتى نتمكن من إظهار الشكل الذي تبدو عليه الخرائط

أهلا!

هل رأيتم يا رفاق بعض المكتبات مثل https://github.com/vladmihalcea/hibernate-types لاستخدامها مع تفاعل السبات؟

إذا لم يكن ذلك موجودًا بعد ، أود بناء شيء لمشروعي (باستخدام quarkus). أستخدم الكثير من أعمدة JSON في postgres.

ولكن أنا لا أعرف ما إذا كنت تحصل على خطأ، ولكن hibernate-reactive السماح فقط لنوع مخصص من خلال تنفيذ من UserType اجهة؟ (http://hibernate.org/reactive/documentation/1.0/reference/html_single/#_custom_types)

AlexandreGuidin ، أعتقد أن gavinking أجاب بالفعل على أسئلتك في أحد التعليقات السابقة: https://github.com/hibernate/hibernate-reactive/issues/279#issuecomment -666289449

ولكن إذا فاتني شيء ما ، فلا تتردد في المتابعة ببعض الأسئلة الأخرى.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات