使用 jOOQ 将枚举值插入到未知表中

Pet*_*ček 5 java postgresql enums jooq

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

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

CREATE TABLE enum_table (
    direction DIRECTION NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

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

我试过的:

  • 根本不用打字:

    context.insertInto(table("enum_table"))
        .columns(field("direction"))
        .values("west")
        .execute();
    
    Run Code Online (Sandbox Code Playgroud)

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

    org.jooq.exception.DataAccessException: SQL [insert into enum_table (direction) values (?)]; ERROR: column "direction" is of type direction but expression is of type character varying.

  • Column type as Enum.class + coercing or casting to Enum.class:

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

    which throws this:

    org.jooq.exception.SQLDialectNotSupportedException: Type class java.lang.Enum is not supported in dialect DEFAULT.

    (Wut? I absolutely have set my dialect to SQLDialect.POSTGRES_9_5.)

  • Creating an ad-hoc enum in 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();
    
    Run Code Online (Sandbox Code Playgroud)

    Also tried an alternative - same result:

    .columns(field("direction", SQLDataType.VARCHAR.nullable(false).asEnumDataType(Direction.class)))
    
    Run Code Online (Sandbox Code Playgroud)

    Throws the incompatible types exception again:

    org.jooq.exception.DataAccessException: SQL [insert into enum_table (direction) values (?)]; ERROR: column "direction" is of type direction but expression is of type character varying.


Is there any way to insert into an "unknown" (not generated) table with an enum column using jOOQ?

Luk*_*der 4

对您现有尝试的评论:

根本不用打字

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

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

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

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

如果您查看堆栈跟踪的起源位置,就会发现它是在您传递Enum.classDSL.field(). 在该静态方法中,上下文中没有方言,因此这就是出现此错误消息的原因。

解决方案

你很接近:

在 Java 中创建临时枚举

在 PostgreSQL 中使用时EnumType,还需要返回Schema引用。这是为了区分EnumType使用 PostgreSQL 或 MariaDB/MySQL 生成的实例。这可能不是绝对必要的。将通过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";
    }
}
Run Code Online (Sandbox Code Playgroud)