将 PostgreSQL JSONB 类型与 Hibernate Reactive 结合使用

Ult*_*ium 1 postgresql hibernate quarkus hibernate-reactive

我正在将我的 Quarkus 项目从经典的 Hibernate ORM 迁移到 Hibernate Reactive,并且遇到了 JSONB 字段映射的问题。

这是实体:

@Entity
@TypeDef(name = JsonTypes.JSON_BIN, typeClass = JsonBinaryType::class)
class MyEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "myEntityIdGenerator")
    @SequenceGenerator(name = "myEntityIdGenerator", sequenceName = "my_entity_id_seq", allocationSize = 10)
    var id: Long? = null

    // Usage of a plain JsonNode instead of a mapped class is intentional, 
    // as the app receives a request with raw JSON data and should store it without any processing
    @Type(type = JsonTypes.JSON_BIN)
    @NotNull
    lateinit var jsonData: JsonNode
}
Run Code Online (Sandbox Code Playgroud)

该项目具有io.quarkiverse.hibernatetypes:quarkus-hibernate-types:0.2.0处理 JSON 类型的依赖项。

这段代码可以很好地阻止 Hibernate API,但是当尝试MyEntity使用 Hibernate Reactive 来持久化时,我得到以下异常:

io.vertx.core.impl.NoStackTraceThrowable: Parameter at position[1] with class = [com.fasterxml.jackson.databind.node.ObjectNode] and value = [{"field1":"some value"}] can not be coerced to the expected class = [java.lang.Object] for encoding.
Run Code Online (Sandbox Code Playgroud)

这是一个错误还是在使用 Hibernate Reactive 时应该以不同的方式处理自定义类型?

Dav*_*lto 6

Hibernate 类型与 Hibernate Reactive 不兼容。

但是您可以通过三种选择来使用 Hibernate Reactive 映射 Json:

  1. 使用io.vertx.core.json.JsonObject
  2. 将其映射为字符串并使用转换器
  3. 创建用户类型

1.Json对象

示例io.vertx.core.json.JsonObject

    @Entity
    private static class EntityWithJson {

        ...

        private JsonObject jsonObj;

...
}
Run Code Online (Sandbox Code Playgroud)

您可以在存储库中看到一个工作示例:JsonTypeTest

2. 使用转换器

使用转换器的示例:

class EntityWithJson {

        @Column(columnDefinition = "json")
        @Convert(converter = StringToJson.class)
        private String json;
...
}

@Converter
public class StringToJson implements AttributeConverter<String, JsonObject> {

    @Override
    public JsonObject convertToDatabaseColumn(String string) {
        if (string == null) {
            return null;
        }
        return new JsonObject(string);
    }

    @Override
    public String convertToEntityAttribute(JsonObject dbData) {

        if (dbData == null) {
            return null;
        }
        return dbData.encodePrettily();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在存储库中看到一个工作示例:JsonTypeTest

3. 用户类型

class EntityWithJson {


        @Type(type="org.example.Json")
        @Column(columnDefinition = "json")
        private JsonObject jsonObj;

}

package org.example

public class Json implements UserType {

   // ... Implementation left out for brevity
}
Run Code Online (Sandbox Code Playgroud)

您可以在存储库中看到一个工作示例:UserJsonTypeTest