在 JOOQ/PostgreSQL 中使用自定义类型更新字段

Update field with custom types in JOOQ/PostgreSQL

PostgreSQL 中有一个 table 带有 ltree 字段。如何用字符串值更新这个字段?

DSL.using(configuration)
.update(AREAS)
.set(AREAS.TREE, area.getTree());//getTree() return String

我尝试了几种变体:

  1. val(area.getTree()).cast(field("ltree")) 投掷

    A org.jooq.exception.DataAccessException has been caught, 
    SQL [update "public"."areas" set "tree" = cast(? as any) where "public"."areas"."id" = ?]; 
    ERROR: syntax error at or near "any"*
    
  2. inline(String.format("CAST(\'%s\' AS ltree)", area.getTree())) 使用多余的引号

    A org.jooq.exception.DataAccessException has been caught, 
    SQL [update "public"."areas" set "tree" = 'CAST(''1.35.1284739'' AS ltree)' where "public"."areas"."id" = ?]; 
    ERROR: syntax error at position 4*
    
  3. val(field("CAST({0} AS ltree)", area.getTree())) 投掷

    A org.jooq.exception.SQLDialectNotSupportedException has been caught, 
    Type class org.jooq.impl.SQLField is not supported in dialect DEFAULT
    

彻底解决

在长 运行 中,添加对供应商特定数据类型的支持的最佳方法是为其指定一个 custom data type binding,它允许您定义 jOOQ 应该如何序列化/反序列化输入 JDBC API,包括您可能需要的转换。

快速获胜可能是这些:

field("CAST(? as ltree)", area.getTree());
field("CAST({0} as ltree)", val(area.getTree()));

这就是您的各种尝试均无效的原因:

val(area.getTree()).cast(field("ltree"))

这种方法乍一看似乎很有意义,因为您正在使用 jOOQ 的内置 cast() 支持。但是,您的 field("ltree") 表达式对未知类型的 named ltree 字段建模,因此当您将其传递给 cast() 时,jOOQ 不知道将 val 投射到什么,因此:any

inline(String.format("CAST(\'%s\' AS ltree)", area.getTree()))

这在您的上下文中没有真正意义,因为 DSL.inline() 创建一个内联绑定变量或常量,或 一个字符串文字 (所有不同的名称同一个概念)。您不需要字符串文字 'CAST(... AS ltree)',您需要表达式 CAST(... AS ltree).

val(field("CAST({0} AS ltree)", area.getTree()))

这与上面的类似,尽管你离这里很近。内部 field(...) 表达式创建一个 SQL 模板,这就是您想要的。但是随后您使用 DSL.val() 将其包装在绑定变量中,这实际上没有意义,原因有两个:

  • 您不希望转换表达式成为绑定变量
  • 转换表达式(Field 类型)不是创建绑定变量的有效类型。 jOOQ 不知道如何绑定 Field
  • 类型的值