Hibernate-reactive: Поддержка настраиваемых типов пользователей

Созданный на 9 июл. 2020  ·  30Комментарии  ·  Источник: hibernate/hibernate-reactive

Привет всем. Поддерживает ли Hibernate Reactive настраиваемые типы пользователей? Я хочу использовать Postgres JSONB Type, и для этого я использовал следующую библиотеку https://github.com/vladmihalcea/hibernate-types, которая создает собственные типы на основе AbstractSingleColumnStandardBasicType Hibernate. К сожалению, при переходе от Hibernate к Hibernate Reactive столбцы, которые используют эти типы, всегда имеют значение NULL в объектах. В качестве альтернативы я нашел эту статью, в которой строится поддержка JSONB Postgres на UserType Hibernate. Есть ли какие-либо известные ограничения в отношении определения пользовательских типов и использования Hibernate Reactive на данный момент?

Все 30 Комментарий

Привет, я не тестировал UserType поскольку этот интерфейс скорее привязан к JDBC. (Хотя в принципе, возможно, это можно было бы заставить в основном работать.)

Вместо этого я решил, что люди могут использовать конвертеры JPA. Я проверил это, и AFAIK это работает. Вы пробовали это?

Я попробовал провести быстрый тест с использованием UserType, но, похоже, он не работает, потому что PgClient выдает исключение при выполнении запроса.

Я попробовал провести быстрый тест с использованием UserType, но, похоже, он не работает, потому что PgClient выдает исключение при выполнении запроса.

Но это может быть просто потому, что наш поддельный слой JDBC не завершен. (Некоторые нереализованные методы.)

Чтобы уточнить, я пробовал пример с использованием библиотеки 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;

Это ошибка:

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

Я думаю, что клиент ожидает объект типа io.reactiverse.pgclient.data.Json . Кажется, мы обрабатываем UserType правильно, хотя

Правильно, это то, что я имел в виду в своем комментарии выше. Наши адаптеры JDBC даже близко не приблизились к полной реализации JDBC, и я считаю весьма вероятным, что этого никогда не произойдет. В частности, для более «экзотических» типов JDBC может быть довольно сложно отобразить их в / из Vert.x API.

Должны ли мы поддерживать какое-то отображение для типов pg-client?

Ну, конечно, если это достаточно легко сделать.

Но если нет, мы должны учесть, что, возможно, UserType здесь просто неподходящая абстракция, и искать другой подход.

Я имею в виду, что в той степени, в которой существующие UserType s можно заставить работать, не делая ничего ужасного, тогда давайте заставим их работать. Это упростит миграцию. Но я думаю, что вполне возможно, что мы быстро столкнемся с ограничениями относительно того, что там действительно возможно.

я взгляну

я взгляну

В качестве первого шага мы должны добавить тест на совершенно простой UserType , который не использует какие-либо причудливые типы баз данных, просто чтобы проверить, работает ли основная концепция (я не понимаю, почему это не должно ).

@gavinking Нет, я еще не тестировал конвертеры, потому что я использую Hibernate вместе с библиотекой Hibernate Types. Но предложение использовать конвертеры означало бы, что в конце концов я добавлю в БД простой Postgres Text / Varchar, а не тип Postgres JSONB.

@gavinking Нет, я еще не тестировал конвертеры, потому что я использую Hibernate вместе с библиотекой Hibernate Types. Но предложение использовать конвертеры означало бы, что в конце концов я добавлю в БД простой Postgres Text / Varchar, а не тип Postgres JSONB.

Чтобы уточнить: вас беспокоит, какой у вас тип в Java или в базе данных? Здесь есть две разные вещи.

  • Один из них - использовать JSONB в качестве типа столбца, но в принципе я бы подумал, что драйверы могут прозрачно преобразовывать строки в этот тип. (Не уверен, никогда не пробовал.)
  • Второй - использовать io.reactiverse.pgclient.data.Json в качестве типа Java в вашей модели. Это совсем другая проблема, и для нее действительно потребуется что-то вроде UserType .

@gavinking
Я хочу использовать тип 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 работают в HR, по крайней мере в той степени, в которой наши адаптеры PreparedStatement и ResultSet являются точной реализацией JDBC ( что не в особо большой степени).

@gavinking Должны ли мы поддерживать какое-то отображение для типов 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)

Итак, теперь возникает вопрос: можем ли мы сделать так, чтобы 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, чтобы дать вам конкретные ответы на ваши первоначальные вопросы:

Поддерживает ли Hibernate Reactive пользовательский UserTypes ?

Ответ положительный!

Тем не менее, вы должны знать, что, хотя мы предоставляем вашему UserType нечто, очень похожее на JDBC, на самом деле это не соединение JDBC, а совершенно другой неблокирующий клиент базы данных. Так что некоторые вещи просто не сработают.

Я использовал следующую библиотеку https://github.com/vladmihalcea/hibernate-types

Так что я думаю, вам нужно отнестись к этому довольно реалистично. Вышеупомянутая библиотека написана для работы с JDBC, поэтому, хотя некоторые из ее UserType s могут работать, другие нет.

В качестве альтернативы я нашел эту статью, которая строит поддержку JSONB Postgres на UserType Hibernate.

Посмотрите, как я реализовал это в тестовом наборе. Основная идея состоит в том, что вам нужно передать 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 String со столбцом типа JSONB?

...

Хорошо, тогда может быть, что клиент Vert.x уже поддерживает это преобразование типов, нам нужно будет его попробовать, но даже если это не так, я думаю, что, вероятно, стоит.

Согласно документации , я связан выше, это работает. Я даже протестировал запись целого числа непосредственно в столбец JSONB -types, и это сработало.

Так что в принципе вам даже не нужно возиться с 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 рейтинги