簡體   English   中英

如何使用 R2dbc 從 Postgresql 中提取 jsonb 到 Spring webflux

[英]How to extract jsonb from Postgresql to Spring webflux using R2dbc

所以我有這個想法真的超出了我的頭腦,因為我只編程了很短的時間,但我想構建一個反應式 Spring webflux 應用程序,將 json 端點暴露給一個反應前端。

當我決定在 Postgres 中使用 jsonb 格式時,問題就開始了,因為我認為我可能會從 DB 到前端層一直使用 json。

當我嘗試使用反應式 R2dbc 驅動程序使用 jsonb 選擇表時,出現以下錯誤:

Caused by: java.lang.IllegalArgumentException: 3802 is not a valid object id

我在 postgres 中有一張看起來像這樣的表:

Column  |  Type   | Collation | Nullable |           Default
---------+---------+-----------+----------+------------------------------
 id      | integer |           | not null | generated always as identity
 details | jsonb   |           |          |
Indexes:
    "snacks_new_pkey" PRIMARY KEY, btree (id)

因此,如果我將其作為文本提取到 Spring webflux,它就可以正常工作,因為它不再是 json。

"SELECT id, details->>'name' as NAME, details->>'price' AS PRICE, details->>'quantity' AS QUANTITY FROM snacks_new"

我已經看到了一些關於如何使用舊的阻塞驅動程序將 jsonb 轉換為 json 對象的示例,但我無法使用較新的非阻塞驅動程序,我無法以任何方式訪問它們。

所以我真的有兩個問題,如何使用反應驅動程序選擇包含 jsonb 的表,我是否在浪費時間嘗試這樣做,是否將 json 提取為文本並從中創建一個普通的 POJO?

謝謝你的時間!

更新:請升級到 R2DBC Postgres 0.8.0.RC1。

該驅動程序最近添加對 JSON 和 JSONB 類型的支持。 您可以使用 JSON 作為Stringbyte[]io.r2dbc.postgresql.codec.Json類型:

// Read as Json
connection.createStatement("SELECT my_json FROM my_table")
        .execute()
        .flatMap(it -> it.map((row, rowMetadata) -> row.get("my_json", Json.class)))
        .map(Json::asString)

// Read as String
connection.createStatement("SELECT my_json FROM my_table")
        .execute()
        .flatMap(it -> it.map((row, rowMetadata) -> row.get("my_json", String.class)))

// Write JSON
connection.createStatement("INSERT INTO my_table (my_json) VALUES($1)")
        .bind("$1", Json.of("{\"hello\": \"world\"}"))
        .execute()

// Write JSON as String using ::JSON casting
connection.createStatement("INSERT INTO my_table (my_json) VALUES($1::JSON)")
        .bind("$1", "{\"hello\": \"world\"}")
        .execute()

請注意,當您想為SELECTINSERTUPDATE綁定 JSON 值時,您必須使用驅動程序Json類型或將綁定值與$1::JSON為 JSON。

如果您想使用 GSON 或 Jackson 在驅動程序級別映射序列化/反序列化值,您還可以利用驅動程序的CodecRegistrar提供您自己的JsonCodec實現。

參考:

更新:

截至撰寫本文時(2019 年 9 月 15 日),他們不支持 JSON,但現在他們確實支持 0.8.0 及更高版本的 JSON

舊答案:

我很抱歉地說,正如你所說,我認為你是在浪費時間

在查看 R2DBC 驅動程序的github 時,您可以在他們的表中看到它們支持的內容,該 json 是截至目前,不支持

正如@mp911de所解釋的那樣,R2DBC 現在包含一個用於Json的編解碼器。 但是將您的實體屬性定義為Stringbyte[]不是很舒服,類型io.r2dbc.postgresql.codec.Json不是很便攜。 此外,如果您想在 REST API 中使用它,您需要定義一個自定義序列化器/反序列化器,如參考資料中所述。

一個更好的選擇是定義一個自定義轉換器io.r2dbc.postgresql.codec.Json from/to JsonNode並使用后面的類型作為您的屬性:

@Configuration
public class ReactivePostgresConfig {

private final ObjectMapper objectMapper;

public ReactivePostgresConfig(ObjectMapper objectMapper) {
    this.objectMapper = objectMapper;
}

@Bean
public R2dbcCustomConversions customConversions() {
    List<Converter<?, ?>> converters = new ArrayList<>();
    converters.add(new JsonToJsonNodeConverter(objectMapper));
    converters.add(new JsonNodeToJsonConverter(objectMapper));
    return R2dbcCustomConversions.of(PostgresDialect.INSTANCE, converters);
}

@ReadingConverter
static class JsonToJsonNodeConverter implements Converter<Json, JsonNode> {
    
    private final ObjectMapper objectMapper;

    public JsonToJsonNodeConverter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    
    @Override
    public JsonNode convert(Json json) {
        try {
            return objectMapper.readTree(json.asString());
        } catch (IOException e) {
            LOG.error("Problem while parsing JSON: {}", json, e);
        }
        return objectMapper.createObjectNode();
    }
}

@WritingConverter
static class JsonNodeToJsonConverter implements Converter<JsonNode, Json> {

    private final ObjectMapper objectMapper;

    public JsonNodeToJsonConverter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    
    @Override
    public Json convert(JsonNode source) {
        try {
            return Json.of(objectMapper.writeValueAsString(source));
        } catch (JsonProcessingException e) {
            LOG.error("Error occurred while serializing map to JSON: {}", source, e);
        }
        return Json.of("");
    }
}
}

參考:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM