【问题标题】:how to use EnumCodec in r2dbc-postgresql如何在 r2dbc-postgresql 中使用 EnumCodec
【发布时间】:2020-07-22 10:14:21
【问题描述】:

我尝试使用最新版本的 r2dbc-postgresql (0.8.4) 中的 EnumCodec 失败,我想知道您是否可以帮助我。

我也使用 spring-data-r2dbc 1.1.1 版。

我从 GitHub 中获取了确切的示例,并在我的 Postgres 中创建了一个枚举类型“my_enum”, 和一个表“sample_table”,其中包含“名称”(文本)和“值”(my_enum)。

然后我按照例子做了:

SQL:

CREATE TYPE my_enum AS ENUM ('FIRST', 'SECOND');

Java 模型:

enum MyEnumType {
  FIRST, SECOND;
}

编解码器注册:

PostgresqlConnectionConfiguration.builder()
.codecRegistrar(EnumCodec.builder().withEnum("my_enum", MyEnumType.class).build());

我使用 DatabaseClient 来与数据库通信。 我尝试使用 2 种方法插入:

databaseClient.insert().into(SampleTable.class)
.using(sampleTable).fetch().rowsUpdated();

或:

databaseClient.insert().into("sample_table")
.value("name", sampleTable.getName())
.value("value", sampleTable.getValue())
.then();

SampleTable 在哪里:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table("sample_table")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SampleTable implements Serializable {
   private String name;
   @Column("value")
   @JsonProperty("value")
   private MyEnumType value;
}

但我同时使用这两种方法都会遇到同样的错误:

列“值”是 my_enum 类型,但表达式是字符变化类型

您能否帮助我理解我做错了什么,或者向我推荐一些工作示例? 感谢您的帮助!

【问题讨论】:

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


    【解决方案1】:

    我尝试在我的示例项目中使用 pg 枚举类型和 Java Enum 类。

    1. 如果你使用DatabaseClient API(在Spring 5.3核心,不使用Spring Data R2dbc),在PostgresConnectionFactory注册一个EnumCodec就足够了。

      检查my exmaple

    2. 如果在表模式中创建一个 pg 类型枚举作为列类型,并在 PostgresConnectionFactory.builder 中注册一个 EnumCodec。您需要编写自定义@ReadingConverter 才能读取自定义枚举。

      检查my example here

    3. 如果在 Java Enum 的表模式中使用基于文本的类型(varchar)。无需额外的转换工作,请查看my example here

    Spring Data R2dbc 说如果使用驱动内置机制来处理枚举,你必须注册一个EnumWriteSupport。但是根据我的经验,在使用Spring Data R2dbc时,可以自动处理写入,但是需要读取转换器才能从Postgres读取枚举。

    【讨论】:

      【解决方案2】:

      Spring Data 默认将枚举值视为要转换为String 的值。您需要注册一个Converter,通过按原样编写枚举类型来保留类型。

      @WritingConverter
      class MyEnumTypeConverter implements Converter<MyEnumType, MyEnumType> {
          @Override
          public MyEnumType convert(MyEnumType source) {
              return source;
          }
      }
      

      接下来,您需要注册转换器。如果您使用 Spring Data R2DBC 的 AbstractR2dbcConfiguration,则覆盖 getCustomConverters()

      class MyConfiguration extends AbstractR2dbcConfiguration {
      
          @Override
          protected List<Object> getCustomConverters() {
              return Collections.singletonList(new MyEnumTypeConverter());
          }
      
        // …
      }
      

      或者,如果您配置 DatabaseClient 独立,那么您需要更多代码:

      PostgresqlConnectionConfiguration configuration = PostgresqlConnectionConfiguration.builder()
              .codecRegistrar(EnumCodec.builder().withEnum("my_enum", MyEnumType.class).build())
              .host(…)
              .username(…)
              .password(…)
              .database(…).build();
      
      R2dbcDialect dialect = PostgresDialect.INSTANCE;
      DefaultReactiveDataAccessStrategy strategy = new DefaultReactiveDataAccessStrategy(dialect, Collections.singletonList(new MyEnumTypeConverter()));
      
      DatabaseClient databaseClient = DatabaseClient.builder()
              .connectionFactory(new PostgresqlConnectionFactory(configuration))
              .dataAccessStrategy(strategy)
              .build();
          
      

      但是,R2DBC 驱动程序中有两个错误会阻止 Spring Data 按预期工作:

      作为临时解决方法,您可以在代码库中复制 EnumCodec 并应用 #302 中的修复,直到新版本的 R2DBC Postgres 可用。

      【讨论】:

      • 谢谢!它似乎有效,但我无法读取使用 databaseClient.select() 时写入的数据 - 我收到“无法从结果集中读取属性”错误。编写 ReadingConverter 的正确方法是什么?
      • 查看上面导致读取行失败的错误参考。
      • 我已按照上述步骤尝试复制 EnumCodec,但出现以下错误:Caused by: java.lang.IllegalArgumentException: 16404 is not a valid object id at io.r2dbc.postgresql.type.PostgresqlObjectId.valueOf(PostgresqlObjectId.java:417) at io.r2dbc.postgresql.codec.AbstractTemporalCodec.canDecode(AbstractTemporalCodec.java:69)
      • 如何在不实现connectionFactory()方法的情况下使用第一个选项(扩展AbstractR2dbcConfiguration)?
      • 检查official example
      猜你喜欢
      • 2020-12-26
      • 2020-01-16
      • 2019-11-08
      • 2020-05-21
      • 1970-01-01
      • 2020-08-24
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      相关资源
      最近更新 更多