前两天写的博客是mybatis的批量更新的操作 今天写一下mybatis的批量更新的相关注意事项
首先 , 本篇文章采用的是比较耗时的方法 ,但是也是比较通用的,
首先 要进行mybatis的批量操作 先要开启批量 也就是在jdbc 连接信息的URL 后面加上&allowMultiQueries=true
这是dao 方法
int updateAllList(List<Map<String, Object>> list);
因为最近一直在做通用的表单和工作模块,所以并不知道数据是什么格式的所以我的sql这么写的
<update id="updateAllList" parameterType="java.util.List" >因为我的数据是封装在map里面的 我遍历map的方式也是上面写的那样 一直没出过错 但是!! 这种
<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>
${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
大家可以参考一下