jooq 在极少数情况下生成不正确的 sql

Mik*_*kke 1 postgresql jooq kotlin spring-boot spring-cloud-gateway

我有一个 Spring Cloud Gateway 应用程序将身份验证数据保存到数据库。应用程序在 kubernetes 中运行。我有太多不同的情况,有时我有 json 数据要保存,有时 json 数据为空。保存此数据的代码如下所示:

    with(AUTHENTICATED_SESSION) {
        context.insertInto(this, ACCESS_TOKEN_MD5_HASH, REFRESH_TOKEN, CONTEXT_DATA)
            .values(
                accessTokenMd5,
                refreshToken,
                if (contextData != null) {
                    JSONB.jsonb(objectMapper.writeValueAsString(contextData))
                } else {
                    null
                }
            )
            .execute()
    }
Run Code Online (Sandbox Code Playgroud)

生成的列定义

public final TableField<AuthenticatedSessionRecord, JSONB> CONTEXT_DATA = createField(DSL.name("context_data"), SQLDataType.JSONB, this, "");
Run Code Online (Sandbox Code Playgroud)

保存空值通常应该像这样:

insert into "public"."authenticated_session" ("access_token_md5_hash", "refresh_token", "context_data") values (?, ?, cast(? as jsonb))
    : -> with bind values      : insert into "public"."authenticated_session" ("access_token_md5_hash", "refresh_token", "context_data") values ('hash', 'token', cast(null as jsonb))
Run Code Online (Sandbox Code Playgroud)

有时查询看起来像这样,它会导致下面的异常

insert into "public"."authenticated_session" ("access_token_md5_hash", "refresh_token", "context_data") values (?, ?, ?)
    : -> with bind values      : insert into "public"."authenticated_session" ("access_token_md5_hash", "refresh_token", "context_data") values ('hash', 'token', null)
Run Code Online (Sandbox Code Playgroud)
org.jooq.exception.DataAccessException: SQL [insert into "public"."authenticated_session" ("access_token_md5_hash", "refresh_token", "context_data") values (?, ?, ?)]; ERROR: column "context_data" is of type jsonb but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.
  Position: 121
    at org.jooq_3.14.6.DEFAULT.debug(Unknown Source) ~[na:na]
    at org.jooq.impl.Tools.translate(Tools.java:2880) ~[jooq-3.14.6.jar:na]
    at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:757) ~[jooq-3.14.6.jar:na]
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:389) ~[jooq-3.14.6.jar:na]
    at org.jooq.impl.AbstractDelegatingQuery.execute(AbstractDelegatingQuery.java:119) ~[jooq-3.14.6.jar:na]
Run Code Online (Sandbox Code Playgroud)

因此,似乎在极少数情况下,jooq 会生成不正确的 sql(未转换为 jsonb)。

这个问题真的很烦人,因为发生这种情况时应用程序根本无法使用。重新启动 Pod 会有所帮助。此问题很可能仅在应用程序启动后出现。

使用的版本:

  • 乔克 3.14.6
  • 春季启动 2.3.5.RELEASE
  • 春季云网关2.2.5.RELEASE
  • Docker 容器中的 Postgresql 10.12
  • postgresql 驱动程序 42.2.5
  • 科特林 1.4.10

Luk*_*der 5

你的问题中有一个提示,每次看到它,我都很高兴实现了这个功能:

 at org.jooq_3.14.6.DEFAULT.debug(Unknown Source) ~[na:na]
Run Code Online (Sandbox Code Playgroud)

DEFAULT指的是SQLDialect.DEFAULT,但它应该是SQLDialect.POSTGRES在你的情况下。您收到无效 SQL 的原因是因为在这些情况下,您没有正确配置Configuration.

这应该可以帮助您找到问题,记住 jOOQQuery对象不是线程安全的。

  • @bedla.czech:https://github.com/jOOQ/jOOQ/blob/a90999b2dada1c0c07dd939244814a1266f87171/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java#L667-L685 (2认同)