使用 ObjectMapper::convertValue() 时保留某些字段的原始类型

Keep original type for certain fields when using ObjectMapper::convertValue()

我想生成一个 Map 对象作为参数传递给 NamedParameterJdbcTemplate::update() 作为现有 POJO 的第二个参数。一个 属性 是类型 java.util.UUID.

@Builder
@Data
static class POJOObject {
  @Builder.Default
  @NonNull
  private UUID id = UUID.randomUUID();
  @NonNull
  private String data;
}

当使用对象映射器映射此对象时,给定的 属性 被序列化为 String 并且数据库操作失败。

var pojo = POJOObject.builder().data("something").build();
Map<String, Object> mapFromPojo = new ObjectMapper().convertValue(pojo, Map.class);
// this throws an exception 
namedParameterJdbcTemplate.update(
    "INSERT INTO pojo_table ( id, data ) VALUES ( :id, :data )",
    mapFromPojo
);
// this works
namedParameterJdbcTemplate.update(
    "INSERT INTO pojo_table ( id, data ) VALUES ( :id, :data )",
    ImmutableMap.of("id", pojo.getId(), "data", pojo.getData()
);

PostgreSQLtable定义如下:

CREATE TABLE pojo_table (
   id   UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
   data TEXT NOT NULL
)

有没有办法使用 ObjectMapper 使 id 键的值类型为 UUID 而不是序列化为 String?或者甚至有 another/better 方法将 POJOObject 实例的数据传递给 NamedParameterJdbcTemplate::update() 调用,而无需手动将字段逐个添加到 Map

这就是更新失败的原因 - 您必须在传递给查询时指定它是 UUID 类型。我认为您最好的选择是手动创建地图 - 这样您在添加值时就不会有任何意外。但你是对的,这就是问题所在。

有一个解决方案,我之前完全监督过:PostgreSQL Cast。为了使其工作,需要修改 SQL 字符串以转换类型,这样地图的所有属性都可以作为 Strings.

传递。

与上面的 POJOObject:

var pojo = POJOObject.builder().data("something").build();

// map can be all strings, when using postgreSQL cast on non-TEXT fields  
namedParameterJdbcTemplate.update(
    "INSERT INTO pojo_table ( id, data ) VALUES ( :id::uuid, :data )",
    new ObjectMapper().convertValue(pojo, Map.class)
);