关于mybatis批量更新操作的相关注意事项

时间:2021-09-25 10:29:04


前两天写的博客是mybatis的批量更新的操作 今天写一下mybatis的批量更新的相关注意事项

首先 , 本篇文章采用的是比较耗时的方法 ,但是也是比较通用的,

首先 要进行mybatis的批量操作 先要开启批量 也就是在jdbc 连接信息的URL 后面加上&allowMultiQueries=true

这是dao 方法

int updateAllList(List<Map<String, Object>> list);

因为最近一直在做通用的表单和工作模块,所以并不知道数据是什么格式的所以我的sql这么写的

  <update id="updateAllList" parameterType="java.util.List" >

<foreach collection="list" item="maps" separator=";">
update ${maps['tableName']} set
<foreach collection="maps.keys" item="k" separator=",">
<if test="k != 'tableName' and k != 'id' and k != 'createTime' and maps[k] != null">
${k} = #{maps[${k}]}
</if>
</foreach>
where id = ${maps['id']}

</foreach>

</update>
因为我的数据是封装在map里面的 我遍历map的方式也是上面写的那样 一直没出过错 但是!! 这种
${k} = #{maps[${k}]}
的遍历方式在批量更新的操作上失效了

具体报错信息如下:

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'maps' not found. Available parameters are [list, collection]
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
at com.sun.proxy.$Proxy16.update(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:55)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53)
at com.sun.proxy.$Proxy17.updateAllList(Unknown Source)
at com.yinsheng.service.impl.WorkServiceImpl.compute(WorkServiceImpl.java:1277)
at com.yinsheng.controller.WorkController.compute(WorkController.java:965)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706)
//后面的就省略了 也没啥用

看到这个错误我以为是我的SQL写的有问题 我把sql打印到控制台后发现一点问题没有 然后我又怀疑 是因为双重foreach的原因 导致我第二个循环中的maps没有读出来

然后经过测试 发现并不是我的sql有问题 而是因为 :

mybatis 在进行批量更新操作的时候  sql不能用#  原因是因为 批量更新时 mybatis 会先把sql全部都拼接好 直接在数据库中运行 而使用# 的方式的话

就相当于一个站位符  是 ? 的效果 所以数据库无法识别

所以sql的拼接得用${}  的方式来进行

${k} = ${maps[k]}


这是一个重要的一点

然后我更改了sql 后 又出现了新的问题


Unknown column '????°‘?–?' in 'field list'

搞得我一脸懵逼 ,  因为我不经常使用${}  来拼接sql 所以很容易忽略一个问题 就是#{} 回自动帮你的数据两端加上' ' 单引号 但是 ${}  是原样输出的

所以我们使用${}  的时候要在数据两端加上' '


  <update id="updateAllList" parameterType="java.util.List" >

<foreach collection="list" item="maps" separator=";">
update ${maps['tableName']} set
<foreach collection="maps.keys" item="k" separator=",">
<if test="k != 'tableName' and k != 'id' and k != 'createTime' and maps[k] != null">
${k} = '${maps[k]}'
</if>
</foreach>
where id = ${maps['id']}

</foreach>

</update>


以上就是 参数是list嵌套map  怎么进行mybatis的批量更新操作 当然这是很耗时的

这里有一篇关于mybatis的优化后的批量更新操作]

https://my.oschina.net/ckanner/blog/338515

大家可以参考一下