如何使用 spring-data-jdbc 读取/写入 postgres jsonb 类型?

San*_*gam 6 postgresql jdbc spring-data spring-boot spring-data-jdbc

我尝试将以下内容与 spring-data-jdbc 和 postgres 驱动程序(kotlin)一起使用,

data class MyEntity(
  val id: UUID,
  val content: String
)
Run Code Online (Sandbox Code Playgroud)

使用字符串失败并出现以下错误,

org.postgresql.util.PSQLException: ERROR: column "content" is of type jsonb but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.
  Position: 31
Run Code Online (Sandbox Code Playgroud)

我不确定如何使用 String -> jsonb 转换器

ein*_*nsA 9

在此帮助下,我实现了以下解决方案:

  1. 引入一个自己的类(POJO / kotlin 数据类),它保存 json 文档的结构(比如说MyContent
  2. 实现一个写入和读取转换器,将 POJO 转换为字符串(例如在 的帮助下jackson
  3. 借助以下命令指定 postgres 列类型org.postgresql.util.PGobject

详细信息(仅伪代码):

import org.springframework.core.convert.converter.Converter
import org.springframework.data.convert.ReadingConverter
import org.springframework.data.convert.WritingConverter
import com.fasterxml.jackson.databind.ObjectMapper
import org.postgresql.util.PGobject

@Table("my_entity")
data class MyEntity(
  @Id val id: UUID,
  val content: MyContent
) {

  @WritingConverter
  class EntityWritingConverter(
      private val objectMapper: ObjectMapper
  ) : Converter<MyContent, PGobject> {
      override fun convert(source: MyContent): PGobject? {
          val jsonObject = PGobject()
          jsonObject.type = "json"
          jsonObject.value = objectMapper.writeValueAsString(source)
          return jsonObject
      }
  }

  @ReadingConverter
  class EntityReadingConverter(
      private val objectMapper: ObjectMapper
  ) : Converter<PGobject, MyContent> {
      override fun convert(pgObject: PGobject): MyContent {
          val source = pgObject.value
          return objectMapper.readValue<MyContent>(source)
      }
  }
}

Run Code Online (Sandbox Code Playgroud)

不要忘记将两个转换器添加到spring-data-jdbcs 配置中(请参阅 参考资料JdbcCustomConversions)。

这适用于相应的 postgres 表:

create table if not exists my_entity
(
    id uuid not null primary key,
    content jsonb
);

Run Code Online (Sandbox Code Playgroud)

  • 作为记录。同时拥有“@ReadingConverter”和“@WritingConverter”以使 spring-data-jbdc 将“MyContent”视为简单类型非常重要。否则 sping-data 将生成带有“JOIN my_content”部分的 SQL。不仅如此,事实上,只有“@WritingConverter”才算数,因为在 spring-data 中它用于注册自定义简单类型。 (2认同)