JOOQ: выбрать, изменить и вставить в ту же таблицу? - PullRequest
0 голосов
/ 03 марта 2020

С родным SQL Я могу выбирать, изменять и вставлять записи в таблицу следующим образом:

INSERT INTO MyTable (url, userName, id)
SELECT url, userName, '27AD2421-83B1-4872-A723-5BDF93688D7C'
FROM WebSite
WHERE id = '27AD2421-83B1-4872-A723-5BDF93688D7B'

Это особенно полезно, поскольку поле идентификатора является первичным ключом.

Я хотел бы сделать то же самое в Java, используя JOOQ, но я не могу понять, как предоставить измененное значение поля.

Возможно ли это, если да, то как?

1 Ответ

1 голос
/ 04 марта 2020

Решение вашей проблемы

Вы можете преобразовать любое значение типа T в выражение типа Field<T>, используя DSL.val() (обычно предпочтительнее) или DSL.inline()

Пояснение к статус-кво

На языке, который поддерживает псевдонимы типов и нетегированные объединения (например, TypeScript, Ceylon), API-интерфейс jOOQ можно определить следующим образом:

// All of these are "column expressions"
type F<T> = T | Field<T> | Select<? extends Record1<T>> | ...;

interface DSLContext {
    <T1>         XYZ<Record1<T1>>         select(F<T1> field1);
    <T1, T2>     XYZ<Record1<T1, T2>>     select(F<T1> field1, F<T2> field2);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(F<T1> field1, F<T2> field2, F<T3> field3);
}

Но, к сожалению, Java не поддерживает это. Единственная опция, которую мы должны эмулировать выше, которая позволила бы смешивать Field<T> и T в списках аргументов, была бы недопустимым количеством перегрузок (N ^ 22 с N = числом типов в F<T> и 22, являющимся максимальная степень, поддерживаемая безопасностью типов jOOQ):

interface DSLContext {

    // Still fine
    <T1>         XYZ<Record1<T1>>         select(T1        f1);
    <T1>         XYZ<Record1<T1>>         select(Field<T1> f1);

    // OK-ish
    <T1, T2>     XYZ<Record1<T1, T2>>     select(T1        f1, T2        f2);
    <T1, T2>     XYZ<Record1<T1, T2>>     select(T1        f1, Field<T2> f2);
    <T1, T2>     XYZ<Record1<T1, T2>>     select(Field<T1> f1, T2        f2);
    <T1, T2>     XYZ<Record1<T1, T2>>     select(Field<T1> f1, Field<T2> f2);

    // Problems start here
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(T1        f1, T2        f2, T3        f3);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(T1        f1, T2        f2, Field<T3> f3);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(T1        f1, Field<T2> f2, T3        f3);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(T1        f1, Field<T2> f2, Field<T3> f3);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(Field<T1> f1, T2        f2, T3        f3);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(Field<T1> f1, T2        f2, Field<T3> f3);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(Field<T1> f1, Field<T2> f2, T3        f3);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(Field<T1> f1, Field<T2> f2, Field<T3> f3);
}

Из-за этой непомерной сложности jOOQ обычно предлагает API только для «всех значений связывания» или «всех выражений». В случае select() случай «всех переменных связывания» настолько редок, что мы решили его опустить:

interface DSLContext {
    <T1>         XYZ<Record1<T1>>         select(Field<T1> f1);
    <T1, T2>     XYZ<Record1<T1, T2>>     select(Field<T1> f1, Field<T2> f2);
    <T1, T2, T3> XYZ<Record1<T1, T2, T3>> select(Field<T1> f1, Field<T2> f2, Field<T3> f3);
}
...