【问题标题】:Insert an enum value into an unknown table with jOOQ使用 jOOQ 将枚举值插入到未知表中
【发布时间】:2023-04-03 09:39:01
【问题描述】:

给定一个带有枚举列的表,如下所示:

CREATE TYPE DIRECTION AS ENUM ('NORTH', 'EAST', 'SOUTH', 'WEST');

CREATE TABLE enum_table (
    direction DIRECTION NOT NULL
);

如何使用 jOOQ 在不为整个表生成 Java 代码的情况下插入上述表?对于这个特定的例子,由于其他技术限制,我(还)不能简单地生成代码。如果有帮助,我可以复制粘贴一段生成的代码(例如类型定义),但整个表格太多了。

我尝试了什么:

  • 根本不用打字:

    context.insertInto(table("enum_table"))
        .columns(field("direction"))
        .values("west")
        .execute();
    

    正如预期的那样,这会引发不兼容的类型:

    org.jooq.exception.DataAccessException: SQL [insert into enum_table (direction) values (?)];错误:“方向”列的类型为 direction,但表达式的类型为 character varying

  • 列类型为Enum.class + 强制或强制转换为Enum.class

    context.insertInto(table("enum_table"))
        .columns(field("direction", Enum.class))
        .values(DSL.coerce("west", Enum.class))  // or DSL.cast(), same result
        .execute();
    

    抛出这个:

    org.jooq.exception.SQLDialectNotSupportedException:方言DEFAULT不支持类型类java.lang.Enum

    (Wut?我绝对已将我的方言设置为SQLDialect.POSTGRES_9_5。)

  • 在 Java 中创建一个临时枚举:

    private enum Direction implements EnumType {
        NORTH, EAST, SOUTH, WEST;
    
        @Override
        public String getLiteral() {
            return this.name();
        }
    
        @Override
        public String getName() {
            return "direction";
        }
    }
    
    // and then
    context.insertInto(table("enum_table"))
        .columns(field("direction", Direction.class))
        .values(Direction.WEST)
        .execute();
    

    还尝试了替代方法 - 结果相同:

    .columns(field("direction", SQLDataType.VARCHAR.nullable(false).asEnumDataType(Direction.class)))
    

    再次抛出不兼容类型异常:

    org.jooq.exception.DataAccessException: SQL [insert into enum_table (direction) values (?)];错误:“方向”列的类型为 direction,但表达式的类型为 character varying


有什么方法可以使用 jOOQ 插入带有枚举列的“未知”(未生成)表?

【问题讨论】:

    标签: java postgresql enums jooq


    【解决方案1】:

    对您现有尝试的评论:

    根本不用打字

    这行不通。 jOOQ(或者更确切地说是 PostgreSQL)需要类型信息来绑定枚举变量。当然,这是一种耻辱,因为从字符串到枚举的转换可以被看作是直接的,所以它可以隐式地完成。但是 PostgreSQL 目前不能这样工作。

    列类型为 Enum.class + 强制或强制转换为 Enum.class

    由于同样的原因,这仍然不起作用。现在,jOOQ 知道我们正在处理一个枚举(它之前知道该值是否为非 null),但我们不知道 PostgreSQL 枚举类型,我们需要将绑定变量转换为该类型。

    关于“(Wut?我绝对将我的方言设置为SQLDialect.POSTGRES_9_5。)”

    如果您查看堆栈跟踪的来源,那就是您将Enum.class 传递给DSL.field() 的时间。在那个静态方法中,上下文中没有方言,所以这就是出现此错误消息的原因。

    解决方案

    你很亲密:

    在 Java 中创建一个临时枚举

    在 PostgreSQL 中使用 EnumType 时,您还需要返回 Schema 引用。这是为了区分使用 PostgreSQL 或 MariaDB/MySQL 生成的 EnumType 实例。这可能不是绝对必要的。将通过https://github.com/jOOQ/jOOQ/issues/7941进行检查

    现在,试试这个:

    private enum Direction implements EnumType {
        NORTH, EAST, SOUTH, WEST;
    
        @Override
        public String getLiteral() {
            return this.name();
        }
    
        @Override
        public Schema getSchema() {
            return MY_SCHEMA;
        }
    
        @Override
        public String getName() {
            return "direction";
        }
    }
    

    【讨论】:

    • 哦!是的,这行得通。我错过了 getSchema() 的 JavaDoc,表明它的需要。谢谢!
    • @PetrJaneček:我也错过了。在实施中发现了它的需要。它可能不需要...
    猜你喜欢
    • 2018-10-03
    • 1970-01-01
    • 2023-03-19
    • 2016-07-03
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    相关资源
    最近更新 更多