繁体   English   中英

jOOQ 无法在 PostgreSQL 模式下为 H2 数据库正确翻译 SQL

[英]jOOQ does not translate SQL properly for H2 database in PostgreSQL mode

问题在于 Postgres ON CONFLICT语法。

版本(Maven 依赖项):

  • PostgreSQL: 42.2.9
  • 乔克:3.12.3
  • h2 数据库:1.4.200
// mocking connection
final Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;Mode=PostgreSQL", "sa", "");
final Settings settings = new Settings().withRenderNameStyle(RenderNameStyle.AS_IS);
Mockito.doReturn(DSL.using(connection, SQLDialect.POSTGRES, settings)).when(mockDbConn).getDSLContext();

// java code for upsert:
dc.insertInto(MY_TABLE)
    .columns(MY_TABLE.TOKEN, MY_TABLE.NAME, MY_TABLE.EMAIL)
    .values(token, name, email)
    .onDuplicateKeyUpdate()
    .set(MY_TABLE.EMAIL, email)
    .execute();

获取以下错误日志(似乎该问题可能是由于[*] (第 4 行 ↓)。我无法理解它为什么出现以及如何删除它):

-- Syntax error in SQL statement:
INSERT INTO PUBLIC.MY_TABLE (TOKEN, NAME, EMAIL)
VALUES (?, ?, ?)
ON CONFLICT ([*]TOKEN, NAME) -- line 4
DO UPDATE SET EMAIL = EXCLUDED.EMAIL;

-- expected "DO";
-- SQL statement:
insert into public.my_table (token, name, email)
values (?, ?, ?)
on conflict (token, name)
do update set email = excluded.email;

-- [42001-200]

如果我将方言从SQLDialect.POSTGRES切换到SQLDialect.H2会发生以下情况:

-- Column "EXCLUDED.EMAIL" not found; SQL statement:
merge into public.my_table using (select 1 one)
on (public.my_table.token = cast(? as varchar) and public.my_table.name = cast(? as varchar))
when matched then update set public.my_table.email = excluded.email
when not matched then insert (token, name, email)
values (cast(? as varchar), cast(? as varchar), cast(? as varchar))

-- [42122-200]

您在 jOOQ API 用法中混合了 3 种方言:

  1. SQLDialect.MYSQL方言,它是产生onDuplicateKeyUpdate()语法的方言。 这可以在各种方言上模拟,但通常最好使用本机语法(SQL 标准MERGE如果可用,或 PostgreSQL 中的ON CONFLICT )。
  2. SQLDialect.POSTGRES方言,这是您的生产目标方言
  3. SQLDialect.H2方言,用于集成测试

考虑到您可能只将 PostgreSQL 作为生产数据库产品,这非常复杂。 我强烈建议您使用testcontainers进行集成测试,这将允许您从等式中删除 H2。 此外,一旦您仅将 PostgreSQL 确定为目标方言,您就可以避免使用onDuplicateKeyUpdate()语法,并使用 jOOQ 的原生onConflict()语法支持以获得更可预测的结果。

如果您继续混合上述 3 种方言,您经常会遇到一些限制,即 jOOQ 或 H2 无法模拟您正在使用的语法。 如果您实际上必须在生产中支持 3 种方言,这只是一种可接受的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM