如何手动在Spring R2DBC中使用JSON或JSONB PostgreSQL数据类型?

4
我正在使用 Spring Boot、Webflux 和 R2DBC(PostgreSQL) 构建一个新的 API。我的其中一个表将拥有一个 JSON 或 JSONB 字段,用于存储动态 JSON 文档。
目前为止,R2DBC 并不支持 PostgreSQL 数据库的 JSON 数据类型。我想知道是否有可能编写一些代码来在存储库中使用它。
我创建了一个简单的测试项目来尝试此操作,但是还没有成功。我可以使用 `org.springframework.data.r2dbc.core.DatabaseClient.execute()` 写入带有 `to_json()` 的查询并保存 JSON 字段,但是之后无法读取它。
测试实体:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table("Test")
public class Test {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", columnDefinition = "serial")
    private Long id;
    @Column(name = "data", columnDefinition = "json")
    private String data;

}

保存方法的工作原理:

public Mono<Integer> save(Test test) {
        return databaseClient.execute("INSERT INTO test (data) VALUES(to_json($1))")
                .bind("$1", test.getData())
                .fetch()
                .rowsUpdated();
    }

读取时出现异常:
java.lang.IllegalArgumentException: Cannot decode value of type java.lang.Object
    at io.r2dbc.postgresql.codec.DefaultCodecs.decode(DefaultCodecs.java:97)
    at io.r2dbc.postgresql.PostgresqlRow.get(PostgresqlRow.java:88)
    at io.r2dbc.spi.Row.get(Row.java:63)
    at org.springframework.data.r2dbc.convert.ColumnMapRowMapper.getColumnValue(ColumnMapRowMapper.java:100)
    at org.springframework.data.r2dbc.convert.ColumnMapRowMapper.apply(ColumnMapRowMapper.java:59)
    at org.springframework.data.r2dbc.convert.ColumnMapRowMapper.apply(ColumnMapRowMapper.java:44)
    at io.r2dbc.postgresql.PostgresqlResult.lambda$map$0(PostgresqlResult.java:71)

根据博客,新的发布候选版本支持它。 - Avinash Anand
以上链接已失效... - Cesar Angiolucci
抱歉,我认为他们删除了发布说明。但是现在在README中,它说支持JSONJSONB。已添加新编解码器 - io.r2dbc.postgresql.codec.Json。新的链接 - Avinash Anand
我刚试了一下,但是我还不能在spring-data-r2dbc中使用这种方法。虽然r2dbc支持已经存在,但还没有在spring-data-r2dbc抽象层中实现。 - Cesar Angiolucci
2个回答

4

使用io.r2dbc.postgresql.codec.Json作为实体属性类型,查看我的帖子了解更多信息。


1

通过查询将json / jsonb转换为TEXT,我能够做到这一点。我不确定这是否是正确的选择,但它有效。

public Mono<Test> findById(Long id) {
    return databaseClient.execute("SELECT id, data::TEXT FROM test WHERE id = $1")
            .bind("$1", id)
            .map(row -> new Test(
                          row.get("id", Long.class),
                          row.get("data", String.class)
                        )
            )
            .one();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接