闲来记录下mybatis的批量操作,写法很简单,mapper中的方法传入一个list,然后xml里循环就好;
批量修改注意点:
循环的list一次过千可能有问题,需要分批次执行,这里以批量修改为例,以前好像遇到过批量新增时候,id数量限制,好像是160(忘记具体原因了),总之批量操作注意数量问题。解决方法:看下面的例子
还有就是,批量操作的时候,获取集合的某一个属性,不需要单独去建一个单个属性的list,可以把对象list传入后,直接用.(点)获取相应属性(例子中倒数第四行)
代码如下:
<update id="对应的方法名">
update 表
set STATUS = #{status}
where ORG_CODE = #{orgCode}
and OUTPATIENT_CODE in
<trim suffixOverrides=" OR OUTPATIENT_CODE IN ()">
<foreach item="tlybMzjs" index="index" collection="对应的list"
open="(" close=")">
<if test="index != 0">
<choose>
<when test="index % 1000 == 999">) OR OUTPATIENT_CODE IN (</when>
<otherwise>,</otherwise>
</choose>
</if>
#{tlybMzjs.outpatientCode}
</foreach>
</trim>
</update>
多个update可以这样:这个要注意,循环中的open和close参数,如果不加这个俩个参数,sql能打印,但是会报错无效字符
<update id="batchUpdateByDeptCode" parameterType="java.util.List">
<foreach collection="list" item="item" index="index" open="begin" close=";end;" separator=";">
UPDATE DEPT_DICT
<set>
<if test="item.deptName != null">
DEPT_NAME = #{item.deptName},
</if>
CREATE_DATE = #{item.createDate},
CREATOR = #{item.creator}
</set>
WHERE DEPT_CODE = #{item.deptCode}
</foreach>
</update>
输出sql结构:多一个begin和end
BEGIN
UPDATE DEPT_DICT
SET DEPT_NAME = ?,
CREATE_DATE = ?,
CREATOR = ?
WHERE
DEPT_CODE = ? ;
UPDATE DEPT_DICT
SET DEPT_NAME = ?,
CREATE_DATE = ?,
CREATOR = ?
WHERE
DEPT_CODE = ? ;
UPDATE DEPT_DICT
SET DEPT_NAME = ?,
CREATE_DATE = ?,
CREATOR = ?
WHERE
DEPT_CODE = ? ;
UPDATE DEPT_DICT
SET DEPT_NAME = ?,
CREATE_DATE = ?,
CREATOR = ?
WHERE
DEPT_CODE = ? ;
UPDATE DEPT_DICT
SET DEPT_NAME = ?,
CREATE_DATE = ?,
CREATOR = ?
WHERE
DEPT_CODE = ? ;
END;
批量新增注意点:
一般在业务中,批量修改用的比较少,但毕竟批量操作效率更高,而且事务控制,日志查看更方便,所以也记录进来
批量新增的时候要注意几点,我以一个参数(只有一个list,里面是对象)为例:
1. 只有一个list参数的时候, 要注意,由于dao层没有使用@param注解,这个时候,在xml中foreach的conllection里就不能使用dao层对应的list属性名,会找不到,只要写list就可以,多个参数的话要对应
2.foreach包含的时候,是包含整个insert语句,而不是只有value,会报错,因为执行的sql不正确
3.在foreach里面的分割符号,是用 ;号,而不是 , 可以随意找个表导出一个sql文件看看就明白,多条插入语句是;号分割
4.如果按批量修改的foreach执行,会发现还是报错,很坑的提醒, 好像是无效字段。这是因为批量执行的时候,mybatis识别不了顺序,循环的时候参数对应放不进去,需要在foreach语句里加上开始和结束标识
正确示例:
注意 foreach里面的 open end separator 属性
<insert id="batchSave" parameterType="java.util.List">
<foreach collection="list" item="item" index="index" open="begin" close=";end;" separator=";">
insert into 表
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="item.id != null">
ID,
</if>
<if test="item.assetsCode != null">
ASSETS_CODE,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="item.id != null">
#{item.id,jdbcType=VARCHAR},
</if>
<if test="item.assetsCode != null">
#{item.assetsCode,jdbcType=VARCHAR},
</if>
</trim>
</foreach>
</insert>
另一种批量新增
<insert id="insertBatch" parameterType="java.util.List">
insert into
EQUIPMENT_MAINTENANCE_INFO (EQUIPMENT_MAINTENANCE_INFO_ID,
EQUIPMENT_INFO_ID,
EQUIPMENT_NO, MAINTENANCE_START, MAINTENANCE_END,
MAINTENANCE_COST, DOWN_TIME, MAINTENANCE_START_DATE,
MAINTENANCE_END_DATE, MODIFY_TIME, FAILURE_FREQUENCY,
CREATE_TIME,
CONFIRM_TIME, CONFIRM_STATUS,CONFIRM_USER
,MAINTENANCE_COUNT,FACT_INFO_CODE
)
select
SEQ_EQUIPMENT_MAINTENANCE_INFO.nextval EQUIPMENT_MAINTENANCE_INFO_ID,
cd.* from(
<foreach collection="list" item="item" separator="union all">
select
#{item.equipmentInfoId,jdbcType=INTEGER},
#{item.equipmentNo,jdbcType=VARCHAR},
#{item.maintenanceStart,jdbcType=VARCHAR},
#{item.maintenanceEnd,jdbcType=VARCHAR},
#{item.maintenanceCost,jdbcType=DECIMAL},
#{item.downTime,jdbcType=VARCHAR},
#{item.maintenanceStartDate,jdbcType=VARCHAR},
#{item.maintenanceEndDate,jdbcType=VARCHAR},
#{item.modifyTime,jdbcType=DATE},
#{item.failureFrequency,jdbcType=VARCHAR},
#{item.createTime,jdbcType=DATE},
#{item.confirmTime,jdbcType=DATE},
#{item.confirmStatus,jdbcType=VARCHAR},
#{item.confirmUser,jdbcType=VARCHAR},
#{item.maintenanceCount,jdbcType=VARCHAR},
#{item.factInfoCode,jdbcType=INTEGER}
from dual
</foreach>
) cd
</insert>
list 参数判空处理:如果批量循环的为条件,需要为list做判空处理:处理方法点这里