【问题标题】:R2DBC and enum (PostgreSQL)R2DBC 和枚举 (PostgreSQL)
【发布时间】:2020-05-21 21:40:30
【问题描述】:

2020 年 8 月 15 日更新:看来 Enum 支持已于 6 月 16 日添加。R2DBC commit

H2DBC 是否支持 PostgreSQL 枚举?我检查了他们git page,但没有提及任何相关内容。如果是,如何使用枚举(INSERT、SELECT)?
让我们说 PostgreSQL 枚举

CREATE TYPE mood AS ENUM ('UNKNOWN', 'HAPPY', 'SAD', ...);

Java 类

@Data
public class Person {
    private String name;
    private Mood mood;
    // ...

    enum Mood{ UNKNOWN, HAPPY, SAD, ...}
}

我试过了:

        // insert
        var person = ...;
        client.insert()
                .table("people")
                .using(person)
                .then()
                .subscribe(System.out::println);

        // select
        var query = "SELECT * FROM people";
        client.execute(query)
                .as(Person.class)
                .fetch().all()
                .subscribe(System.out::println);

但我收到错误消息:

# on insert
 WARN [reactor-tcp-epoll-1] (Loggers.java:294) - Error: SEVERITY_LOCALIZED=ERROR, SEVERITY_NON_LOCALIZED=ERROR, CODE=42804, MESSAGE=column "mood" is of type mood but expression is of type character varying, HINT=You will need to rewrite or cast the expression., POSITION=61, FILE=parse_target.c, LINE=591, ROUTINE=transformAssignedExpr
# on select
ERROR [reactor-tcp-epoll-1] (Loggers.java:319) - [id: 0x8581acdb, L:/127.0.0.1:39726 ! R:127.0.0.1/127.0.0.1:5432] Error was received while reading the incoming data. The connection will be closed.
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.data.mapping.MappingException: Could not read property private ...

我找到了similar post,但没有运气解决我的问题..也许我应用错了..
欢迎任何帮助或提示。

【问题讨论】:

    标签: postgresql enums spring-data spring-data-r2dbc r2dbc


    【解决方案1】:

    使用org.springframework.data:spring-data-r2dbc:1.0.0.RELEASEio.r2dbc:r2dbc-postgresql:0.8.1.RELEASE 测试。

    Kotlin 版本。

    1. 定义一个枚举类

      enum class Mood {
          UNKNOWN,
          HAPPY,
          SAD
      }
      
    2. 创建自定义编解码器

      class MoodCodec(private val allocator: ByteBufAllocator) :  Codec<Mood> {
          override fun canEncodeNull(type: Class<*>): Boolean = false
      
          override fun canEncode(value: Any): Boolean = value is Mood
      
          override fun encode(value: Any): Parameter {
              return Parameter(Format.FORMAT_TEXT, oid) {
                  ByteBufUtils.encode(allocator, (value as Mood).name)
              }
          }
      
          override fun canDecode(dataType: Int, format: Format, type: Class<*>): Boolean = dataType == oid
      
          override fun decode(buffer: ByteBuf?, dataType: Int, format: Format, type: Class<out Mood>): Mood? {
              buffer ?: return null
              return Mood.valueOf(ByteBufUtils.decode(buffer))
          }
      
          override fun type(): Class<*> = Mood::class.java
      
          override fun encodeNull(): Parameter =
              Parameter(Format.FORMAT_TEXT, oid, Parameter.NULL_VALUE)
      
          companion object {
              // Get form `select oid from pg_type where typname = 'mood'`
              private const val oid = YOUR_ENUM_OID
          }
      }
      
    3. 注册编解码器

      您可能需要将runtimeOnly("io.r2dbc:r2dbc-postgresql") 更改为implementation("io.r2dbc:r2dbc-postgresql")

      @Configuration
      @EnableR2dbcRepositories
      class AppConfig : AbstractR2dbcConfiguration() {
          override fun connectionFactory(): ConnectionFactory = PostgresqlConnectionConfiguration.builder()
              .port(5432) // Add your config here.
              .codecRegistrar { _, allocator, registry ->
                  registry.addFirst(MoodCodec(allocator))
                  Mono.empty()
              }.build()
              .let { PostgresqlConnectionFactory(it) }
      }
      

    【讨论】:

    • R2dbc Postgres 驱动程序包括一个内置的EnumCodec 以支持 Postgres 中的enum 类型。
    • 嗨@Hantsy,枚举对另一种数据库(如oracle、mssql等)的支持怎么样
    • 嗨@Hantsy,你能帮忙重新回答吗?
    猜你喜欢
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2015-05-23
    • 2020-09-14
    • 2020-08-17
    • 2015-03-04
    • 1970-01-01
    • 2013-01-29
    相关资源
    最近更新 更多