Можно ли вручную использовать типы данных JSON или JSONB postgresql с пружиной r2dbc?

Я собираю новый API с весенней загрузкой, webflux и r2dbc (postgresql). В одной из моих таблиц будет поле json или jsonb для хранения динамического документа json.

На данный момент r2dbc не поддерживает типы данных json для базы данных postgresql. Мне интересно, если это возможно использовать в любом случае, написание кода для хранилища.

Я создал простой тестовый проект, чтобы попробовать это, но пока безуспешно. Мне удалось сохранить поле JSON с помощью org.springframework.data.r2dbc.core.DatabaseClient.execute() и оборачивая поле JSON to_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)

1 ответ

Использовать io.r2dbc.postgresql.codec.Jsonв качестве типа свойства вашего объекта, проверьте мой пост об этом.

Я смог сделать это, приведя 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();
}
Другие вопросы по тегам