Hibernate-reactive: 支持自定义用户类型

创建于 2020-07-09  ·  30评论  ·  资料来源: hibernate/hibernate-reactive

大家好。 Hibernate Reactive 是否支持自定义用户类型? 我想使用 Postgres JSONB 类型,为此我使用了以下库https://github.com/vladmihalcea/hibernate-types它基于 Hibernate 的AbstractSingleColumnStandardBasicType构建它的自定义类型。 不幸的是,只是从 Hibernate 移动到 Hibernate Reactive,使用这些类型的列在实体中始终为空。 作为替代,我发现这篇文章在 Hibernate 的UserType上构建了它的 JSONB Postgres 支持。 目前在定义自定义类型和使用 Hibernate Reactive 方面是否有任何已知限制?

design

所有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可以在不做任何可怕的事情的情况下工作,那么当然,让我们让他们工作。 这将使迁移更容易。 但我认为我们可能很快就会遇到真正可能发生的事情的限制。

我会看一下

我会看一下

作为第一步,我们应该为一个完全普通的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在 HR 中是有效的,至少在我们的PreparedStatementResultSet适配器是 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)

所以现在的问题变成了:我们能否让 JDBC 适配器中的getObject()setObject()支持这些类型而不创建对 PostgreSQL 客户端的硬依赖?

是否有可能有类似的东西:

@Type(type="passthrough")
Circle circle

那不做任何转换,只是按原样传递值?

所以现在的问题变成了:我们能否让 JDBC 适配器中的getObject()setObject()支持这些类型而不创建对 PostgreSQL 客户端的硬依赖?

嗯,我已经试过了,显然我们实际上不需要做任何特殊的事情来处理 Postgres 或 MySQL 上的io.vertx.core.json.JsonObject 。 您可以只使用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可能会工作,但其他人不会。

作为替代方案,我发现这篇文章在 Hibernate 的UserType上构建了它的 JSONB Postgres 支持。

看看我是如何在测试套件中实现的。 基本思想是您需要通过调用setObject()将 Vert.x JsonObject传递给 Vert.x PostgreSQL 或 MySQL 客户端。

其他类型呢,例如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 -types 列并且它起作用了。

所以原则上如果你不想,你甚至不需要搞乱JsonObject 。 (不过它可能更干净。)

当然,您能否为其他一些特定类型添加测试? 像线或圆。 这样我们就可以显示映射的样子

你好!

你们有没有看到像https://github.com/vladmihalcea/hibernate-types这样的库与 hibernate-reactive 一起使用?

如果那还不存在,我想为我的项目构建一些东西(使用 quarkus)。 我在 postgres 中使用了很多 JSON 列。

但是我不知道我是否弄错了,但是hibernate-reactive只允许通过从UserType接口实现自定义类型? (http://hibernate.org/reactive/documentation/1.0/reference/html_single/#_custom_types)

@AlexandreGuidin ,我认为@gavinking已经在之前的评论之一中回答了您的问题: https :

但是,如果我遗漏了什么,请随时提出更多问题。

此页面是否有帮助?
0 / 5 - 0 等级