Вставьте значение enum в неизвестную таблицу с помощью jOOQ - PullRequest
0 голосов
/ 15 октября 2018

Имеется таблица со столбцом enum, например:

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" имеет тип 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: Тип класса java.lang.Enum не поддерживается в диалекте DEFAULT.

    (Но я абсолютно установил мой диалект на 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" имеет тип direction, но выражение имеет тип character varying.


Есть ли способ вставить в "неизвестное"(не сгенерированная) таблица со столбцом enum с использованием jOOQ?

1 Ответ

0 голосов
/ 17 октября 2018

Комментарии к вашим существующим попыткам:

Совсем не печатать

Это не работает.jOOQ (или, скорее, PostgreSQL) нужна информация о типе для привязки переменной enum.Это, конечно, позор, потому что преобразование из строк в перечисления можно рассматривать как прямое, так что это может быть сделано неявно.Но PostgreSQL в настоящее время не работает таким образом.

Тип столбца как Enum.class + приведение или приведение к Enum.class

Это все еще не работает, потому чтопо той же причине.Теперь jOOQ знает, что мы имеем дело с перечислением (он знал раньше, если значение было не нулевым), но мы не знаем тип перечисления PostgreSQL, к которому нам нужно привести переменную bind.

Относительно "(Wut? Я абсолютно установил свой диалект на SQLDialect.POSTGRES_9_5.)" :

Если вы посмотрите, откуда происходит трассировка стека, это когда вы передаете Enum.class до DSL.field().В этом статическом методе диалект в контексте отсутствует, поэтому появляется это сообщение об ошибке.

Решение

Вы были близки:

Создание объявленияhoc enum в Java

При использовании EnumType в PostgreSQL вам также необходимо вернуть ссылку 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";
    }
}
...