没有配置该参数的时候,一条更新(update、insert)就代表了向Mysql发送一条语句
可以实现
多条更新语句合并提交给mysql
,他会把多条更新语句,拼接成一条语句发送给mysql
在
数据库连接
中的设置
URL
把参数加上即可
没有报错信息
故障排查过程
经过排查,发现是业务更新数据库走的是
jdbcTemplate.batchUpdate
,并且加了
rewriteBatchedStatements
这个参数才导致更新失败
那么我们仔细看看
batchUpdate
这个方法。
当我们继续往里面跟,就会直接去到第三方源码里面了:
JdbcTemplate.batchUpdate
这边我们可以很清晰地看到在Spring的JdbcTemplate是注册了一个
PreparedStatement
回调函数。
这个回调函数其实就是Spring用来接受数据库语句执行后的结果。
我们再进下一层
ps.executeBatch
PreparedStatement.executeBatch
看到这里其实已经能看到我们这个参数
rewriteBatchedStatements
判断是否开启的地方了
抑或是我们可以通过直接搜索这个参数,去看引用他的地方,也非常好定位
同样也能定位到刚刚那个地方。
我们可以看到这个参数要起作用还要满足一些条件:
版本号要大于
4.1.0
要有更新数据
并且数量要大于3条sql
否则还是去走一条一条sql。
到这里,我们再进下一层
executePrepareBatchAsMultiStatement
PreparedStatement.executePrepareBatchAsMultiStatement
看到开头我就非常敏感,
他这里是直接拼接一个分号
“
;
”到语句里面。而且我们看到他的注释:
“这是一种比较滥用的方式,但是确实能够解决问题”
异常出现的地方
因为框架里面会给我们的语句添加一个分号 ; 如果我们在原语句也有分号,那么就会有2个分号,引起语法错误
加上参数
rewriteBatchedStatements
能很大程度上提高我们对数据批量写入的能力
注意
:
原sql语句结尾不要带分号;
为什么没有
报错信息
?
为什么批量更新
只有一行数据能更新成功
?
问题1:无报错信息
这边是捕获
DataACcessEXception
异常,我看可以看看他的继承关系图:
然后我们去看看框架里面batchUpdate,捕获的是也是
DataAccessException
异常。
我们再进下一里面一层查看,直接去看他在接口的定义,发现他抛的是
SQLException
查看的继承关系图:
这2个异常八竿子打不着,所以我们修改为抛父类的异常,这样在应用层面就能捕获到异常
修改完了之后查看一下报错信息:
不过我们一般不能直接写
e.printStackTrace
,好像是在阿里的Java规范手册里面说禁止这种写法。
改成这种会比较好
def updateBatch(sql: String, argList: List[Array[Any]]): Unit = {
FrequentChecker.sqlRecord(sql)
try {
jdbcTemplate.batchUpdate(sql, argList.map(_.map(_.asInstanceOf[AnyRef])).asJava)
} catch {
case e: Exception => logger.error(s"updateBatch error, sql: ${sql}, error message: ${e.getMessage}")
问题2:只有一行数据能更新成功