JDBC 准备好的语句创建了一个额外的数据库命中,没有任何参数

JDBC prepared statement creates one extra database hit without any params

我有一个烦人的问题,我不明白为什么会这样。简单介绍一下,我在我的 Spring 引导项目中使用 MySql 和 JDBC 模板实现了批处理(批量插入)。

所以基本上批量插入工作正常,性能真的很棒,但是有一个小问题真的很烦人,当我插入一个 table 时它会导致约束异常两列 (id, value) 上的唯一键。

所以我有这个代码:

private String INSERT_SQL_PARAMS = "INSERT INTO item_params(p_key, p_value, item_id) values (?,?,?)"

override fun saveParams(configParams: Set<ItemParam>) {
    jdbcTemplate!!.update { connection ->
        connection.autoCommit = false
        val ps: PreparedStatement = connection.prepareStatement(INSERT_SQL_PARAMS)

        configParams.forEachIndexed { index, it ->
            ps.setLong(1, it.configurationId)
            ps.setString(2, it.pKey)
            ps.setString(3, it.pValue)
            ps.addBatch()

            if (index != 0 && index % 1000 == 0) {
                ps.executeBatch()
                connection.commit()
            }
        }

        ps.executeBatch()
        connection.commit()
        ps
    }
}

当我在 spring 引导中使用数据源代理查看日志时,我可以看到实际执行的查询。

所以当我想一次插入例如 2 个项目时,我在日志中看到了这个:

Batch: True, INSERT INTO item_param(item_id, p_key, p_value) values (1, 1, 1), (2, 2, 2)
Batch: False, INSERT INTO item_param(item_id, p_key, p_value) values ()

正如您所看到的,我总是在最后看到一个没有任何值的 extra/spare 语句,出于某种原因,日志显示 Batch = False。

任何人都可以看到我在代码中遗漏的东西吗?为什么会这样?我可以用它做什么?

还有一个问题,比如我有1000条记录,我会执行batch 2次,一次在if语句中,一次在最后。有什么方法可以让我仅在查询中有参数时才说 ps.executeBatch 吗?

因为jdbcTemplate.update为你执行了你的SQL,所以它会在你的代码末尾自动调用execute

由于它只调用了一次 execute,因此不符合您的目的。试试这个使用 jdbcTemplate.batchUpdatetutorial。它为您实现了对 jdbcConnection 的多次调用。