jOOQ:事务处理期间MySQL“临时表”不存在?

zi8p0yeb  于 2023-02-28  发布在  Mysql
关注(0)|答案(1)|浏览(136)

我有如下代码:

fun <T> withTempTableTxn(
    ctx: DSLContext,
    tempTableSelectAs: org.jooq.Select<*>,
    txnBlock: (DSLContext, org.jooq.Name) -> T,
): T {
    val uuid = UUID.randomUUID().toString().replace("-", "_")

    val tempTableName = DSL.name("temp_table_$uuid")
    val createTempTable = DSL.createGlobalTemporaryTable(tempTableName).`as`(tempTableSelectAs)

    return ctx.transactionResult { txn ->
        txn.dsl().execute(createTempTable)
        val res = txnBlock(txn.dsl(), tempTableName)
        txn.dsl().execute(DSL.dropTemporaryTableIfExists(tempTableName))
        res
    }
}

private fun updateMutation(
    mutationRequest: MutationRequest,
    op: UpdateMutationOperation,
    ctx: DSLContext,
): MutationOperationResult {
    // The rows that the temporary table will be populated with
    val tempTableRows = DSL
        .selectFrom(DSL.table(DSL.name(op.table.value)))
        .where(/* ... */)

    return withTempTableTxn(ctx, tempTableRows) { txn, tempTableName ->
        // ...
    }
}

运行此命令时,似乎找不到临时表。

请注意,如果我用常规表替换temporaryTable,则一切正常

如果我把.also { println(ctx.render(it)) }加到createTempTable上,我们得到:

Creating temp table:
create temporary table `temp_table_e2fd79a5_4589_41df_9972_8ff9b216300a`
as
select *
from `Chinook`.`Artist`
where `Artist`.`Name` = 'foobar'

13:48:02 ERROR traceId=, parentId=, spanId=, sampled= [io.ha.ap.ExceptionHandler] (executor-thread-0) Uncaught exception: org.jooq.exception.DataAccessException: SQL [update `temp_table_e2fd79a5_4589_41df_9972_8ff9b216300a`
set
  `Name` = 'foobar new'
where `temp_table_e2fd79a5_4589_41df_9972_8ff9b216300a`.`Name` = 'foobar'];
Table 'Chinook.temp_table_e2fd79a5_4589_41df_9972_8ff9b216300a' doesn't exist
fcg9iug3

fcg9iug31#

From the docs
创建表时可以使用TEMPORARY关键字。TEMPORARY表仅在当前会话中可见,并且在会话关闭时会自动删除。这意味着两个不同的会话可以使用相同的临时表名,而不会相互冲突,也不会与现有的同名非TEMPORARY表冲突。
其他RDBMS具有临时表,其元数据在会话/事务之间共享,仅在提交时截断数据,但在MySQL中不截断。
就jOOQ而言,最有可能的解释是您使用txn.dsl()(事务1)创建和删除表,但您使用ctx运行txnBlockctx也在作用域中,但运行的是不同的事务,因此它看不到您的txn的临时表。

相关问题