MyBatis3+ 实现批量更新

要实现批量更新,首先得设置mysql支持批量操作,在jdbc链接中需要附加&allowMultiQueries=true属性才行
例如:
jdbc:mysql://localhost:3306/dbname?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true

  • 更新单条记录
    UPDATE course SET name = 'course1' WHERE id = 'id1';
  • 更新多条记录的同一个字段为同一个值
    UPDATE course SET name = 'course1' WHERE id in ('id1', 'id2', 'id3);
  • 更新多条记录为多个字段为不同的值
    比较普通的写法,是通过循环,依次执行update语句。
    Mybatis写法如下:
<update id="updateBatch"  parameterType="java.util.List">  
    <foreach collection="list" item="item" index="index" open="" close="" separator=";">
        update course
        <set>
            name=${item.name}
        set>
        where id = ${item.id}
    foreach>      
update>

一条记录update一次,性能比较差,容易造成阻塞。

  • MySQL没有提供直接的方法来实现批量更新,但可以使用case when语法来实现这个功能。
UPDATE course
    SET name = CASE id 
        WHEN 1 THEN 'name1'
        WHEN 2 THEN 'name2'
        WHEN 3 THEN 'name3'
    END, 
    title = CASE id 
        WHEN 1 THEN 'New Title 1'
        WHEN 2 THEN 'New Title 2'
        WHEN 3 THEN 'New Title 3'
    END
WHERE id IN (1,2,3)

这条sql的意思是,如果id为1,则name的值为name1,title的值为New Title1;依此类推。

在Mybatis中的配置则如下:

<update id="updateBatch" parameterType="list">
     update course
      <trim prefix="set" suffixOverrides=",">
       <trim prefix="peopleId =case" suffix="end,">
           <foreach collection="list" item="i" index="index">
                   <if test="i.peopleId!=null">
                    when id=#{i.id} then #{i.peopleId}
                   if>
           foreach>
        trim>
        <trim prefix=" roadgridid =case" suffix="end,">
           <foreach collection="list" item="i" index="index">
                   <if test="i.roadgridid!=null">
                    when id=#{i.id} then #{i.roadgridid}
                   if>
           foreach>
        trim>

        <trim prefix="type =case" suffix="end," >
           <foreach collection="list" item="i" index="index">
                   <if test="i.type!=null">
                    when id=#{i.id} then #{i.type}
                   if>
           foreach>
        trim>
        <trim prefix="unitsid =case" suffix="end," >
            <foreach collection="list" item="i" index="index">
                    <if test="i.unitsid!=null">
                     when id=#{i.id} then #{i.unitsid}
                    if>
            foreach>
     trim>
    trim>
    where
    <foreach collection="list" separator="or" item="i" index="index" >
        id=#{i.id}
    foreach>
update>

上面是使用xml配置文件进行的批量修改,另外,更详细的介绍可以参考这位老哥哥的博客
下面看使用注解如何写批量更新操作:

使用注解批量更新

首先定义批量更新的接口,参数使用@Param注解界定;

public interface WarningMapper {
    @UpdateProvider(method = "updateBatch", type = WarningProvider.class)
    int updateBatch(@Param(value = "list") List records);
}

提供provider:

class WarningProvider {
    public String updateBatch(final Map> map) {
        List records = map.get("list");//注意这里参数是map获取list
        StringBuilder sb = new StringBuilder();
        sb.append("update " + TABLE_NAME);
        sb.append(" set now_value = case appid");//这里可以仿照set now_value 设置其他值的修改
        MessageFormat mfNowValue = new MessageFormat("#'{'list[{0}].now_value'}'");
        for (int i = 0; i < records.size(); i++) {
            sb.append(" when ");
            sb.append(records.get(i).getAppid());
            sb.append(" then ");
            sb.append(mfNowValue.format(new Object[] { i }));
        }
        sb.append(" end ");
        sb.append("where appid in");
        sb.append("(");
        for (int size = 0; size < records.size(); size++) {
            sb.append(records.get(size).getAppid());
            if (size < records.size() - 1) {
                sb.append(",");
            }
        }
        sb.append(")");
        return sb.toString();
    }
}

上面主要注意表达式"#'{'list[{0}].now_value'}'"的使用

批量插入操作也可以参考批量更新,比较简单不需要case语句


这里在介绍一下Mybatis的常用注解

MyBatis常用注解

  • 查询注解@Select
  • 删除注解@Delete
  • 插入注解@Insert
  • 更新注解@Update
  • @SelectProvider@DeleteProvide@InsertProviderr@UpdateProvider
  • @Options注解

@Options常用属性:

  • flushCache:刷新缓存策略,有DEFAULT,TRUE,FALSE三种值,默认DEFAULT表示刷新查询语句的缓存
  • useCache:默认true,表示使用缓存
  • fetchSize:查询时的获取数量
  • useGeneratedKeys:默认false,是否返回插入的id
  • keyProperty:实体类id属性
  • keyColumn:实体类属性对应数据库的字段

举例:一个插入数据操作的mapper定义如下:

public interface WarningMapper {

    @Insert(value = "insert into dtjx_warning"
            + " (trans_id,monitor_type,creator,created,filter,version)"
            + " values (#{trans_id},#{monitor_type},#{creator},#{created},#{filter},version+1)")
    @Options(keyProperty = "appid", useGeneratedKeys = true, keyColumn = "appid") // 用options属性的useGenerateKeys可以返回自动增长的主键信息
    int insert(WarningModel record);
}

更多注解使用方法,请参考官方文档

你可能感兴趣的:(编程,mybatis)