【问题标题】:JDBC prepared statement creates one extra database hit without any paramsJDBC 准备语句创建一个额外的数据库命中,没有任何参数
【发布时间】:2020-03-27 21:37:55
【问题描述】:

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

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

所以我有这个代码:

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 Boot 中使用数据源代理查看日志时,我可以看到实际执行的查询。

所以当我想一次插入例如 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 ()

所以你可以看到我总是在最后看到一个没有任何值的额外/备用语句,并且由于某种原因日志说 Batch = False。

谁能看到我的代码中缺少的东西,为什么会发生这种情况以及我能用它做什么?

我还有一个问题,例如,如果我有 1000 条记录,我将执行 2 次批处理,一次在 if 语句中,一次在最后。有什么方法可以让我说 ps.executeBatch 只有在查询中有参数的情况下?

【问题讨论】:

  • 您的代码在恰好插入 1000/2000/3000/... 项时有一个小错误。 ps.executeBatch() 将在循环内运行一次,然后在循环外再次以空批处理运行。你在调试的是这种情况吗?
  • 我实际上怀疑这一点,我通过插入 3 个项目对此进行了测试,因此它永远不会进入该 if 语句。但是我再次有额外的插入调用......我实际上用这种情况更新了问题,你有没有建议我只有在查询中有一些参数时才能执行查询?
  • 保留一个额外的布尔值,在 addBatch 时将其设置为 true,在 executeBatch 时将其设置为 false ?
  • 附注 - 如果您的应用程序的插入量很大并且批处理速度不够快,您应该尝试批量插入 CSV。它比批处理快得多。
  • 感谢您的建议,是的,这应该可以在添加批次时保持布尔值!是的,我知道使用 CSV 的“技巧”,但是批量应该没问题,它不像我会处理数百万个插入。

标签: hibernate spring-boot jdbc spring-jdbc jdbctemplate


【解决方案1】:

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

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

【讨论】:

  • 非常感谢你,我今天晚些时候会试试这个,如果一切都按预期工作,我会接受你的回答!
  • 这正是我所需要的,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2017-06-12
  • 2013-01-15
  • 2014-03-10
  • 2015-10-24
  • 2018-02-06
  • 1970-01-01
  • 2019-09-13
  • 1970-01-01
相关资源
最近更新 更多