• mybatis 批量处理更新(增删改)操作


    进行处理操作的时候,又可能进行批量操作的时候,有可能产生错误,原因是因为有些数据库默认允许传递的数据量是有限制的,

    mysql默认是1M,如果是这种情况,需要在mysql的配置文件(my.ini)中的mysqld这个组里面添加max_allowed_packet=10M

    我们先来看下批量增加操作:

    当然我这里只是说明在mapper映射文件的配置,至于dao层就要简单的多:

    mapper.xml

    <insert id="insertBatch">
    insert into dept(deptname) values
    <foreach collection="list" item="dept" separator=","> (#{deptname}) </foreach> </insert>

    当然dao层的参数应该是一个List<dept>集合。

    批量删除操作:

    同样的删除操作是根据id来删除的,所以在dao层只需要传入一个List<Integer>的参数就好。

    mapper.xml

    <delete id="deleteBatch">
        delete from dept where
         <foreach collection="list" item="key" separator="or">
                id=#{key}
        </foreach>
    </delete>

    下面来说说怎么在mybatis中批量修改操作的。这里有三种方法:

    第一种:

    利用分号分割多个sql语句来实现,需要在jdbc的连接url中添加 allowMultiQueries=true这个选项即可。但是这个操作,mysql和sqlserver是支持的,

    oracle数据库好像不支持;

    mapper.xml

    <update id="updateBatch">
        <foreach collection="list" item="dept" separator=";">
            update dept set deptname=#{dept.deptname}
            where id=#{dept.id}
        </foreach>
    </update>

    第二种,这种批量更新方式不需要设置jdbc的url的allowMultiQueries=true

    因为它只有一条update语句。这也是比较推荐大家使用的。

    先来个简单点的,数据库只有一个列(字段)的mapper.xml配置

    mapper.xml

    <update id="updateBatch">
        update dept set
        <trim prefix="deptname=case" suffix="end">
        <foreach collection="list" item="dept">
            when id=#{dept.id} then #{dept.deptname}
        </foreach>
        </trim>
        <where>
            <foreach collection="list" item="dept" separator="or">
                id=#{dept.id}
            </foreach>
        </where>
    </update>

    下面这个就是对数据多个列(多个字段)的处理以及判断是否为空

    <update id="updateBatch">
        update employee
        <trim prefix="set" prefixOverride=";">
            <trim prefix="user_name=case"  suffix="end,">
                <foreach collection="list" item="emp">
                    <if test="emp.username != null and emp.username != '''>
                when id=#{emp.id} then #{emp.username}
                    </if>
                </foreach>
            </trim>
            
            <trim prefix="salary=case"  suffix="end,">
                <foreach collection="list" item="emp">
                    <if test="emp.salary!= null and emp.salary != '''>
                when id=#{emp.id} then #{emp.salary}
                    </if>
                </foreach>
            </trim>
            
            <trim prefix="gender=case"  suffix="end,">
                <foreach collection="list" item="emp">
                    <if test="emp.gender!= null and emp.gender!= '''>
                when id=#{emp.id} then #{emp.gender}
                    </if>
                </foreach>
            </trim>
        </trim>
        <where>
            <foreach collection="list" item="emp" separator="or">
                id=#{emp.id}
            </foreach>
        </where>
    </update>

    上面这两种批量操作的方式性能比较高,但是不是纯粹意义上jdbc的批处理,大家都可能了解jdbc的批处理是利用prepareStatement的

    addBatch() ,executeBatch()这两个方法来完成的。

    所以下面这个种就是利用mybatis对jdbc的批处理来完成的

    先来看看映射文件的写法:

    这里说下,因为这个批处理要用到java代码,所以说在xml配置方面会变得简单多。不像上面两种进行语句的拼接

    mapper.xml

    <update id="update">
        update employee
        <set>
            <if test="username !=null and username != ''">
            user_name = #{username}
            </if>
            <if test="salary!=null and salary != ''">
                salary= #{salary}
            </if>
            <if test="gender!=null and gender != ''">
                gender= #{gender}
            </if>
          </set>
    </update>

    以上代码的dao层都需要一个用到interface下的方法,这里我就举例第三种的写法

    public interface EmployeeDao{
        //注意这个接口是不需要实现的
        void update(Employee employee);
    }

    然后utils层的写法

    public class SqlSessionFactoryUtil {
    
    
        private static final String CONFIG_FILE_PATH = "mybatis-config.xml";
    
        private static  SqlSessionFactory factory = null;
    
        static {
            try {
                InputStream inputStream = Resources.getResourceAsStream(CONFIG_FILE_PATH);
                factory = new SqlSessionFactoryBuilder().build(inputStream);
    
    
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("读取文件失败");
            }
    
        }
    
        public  static  SqlSessionFactory getFactory(){
            return factory;
        }
    
    
        public static SqlSession getSession(){
            return factory.openSession(true);
        }
    }

    然后是service层的写法

    public class EmployeeService{
        public void update(List<Employee> employees>{
            SqlSessionFactory factory = SqlSessionFactoryUtil.getFactory();
            SqlSession session = factory.openSession(ExecutorType.BATCH);
            EmployeeDao employeeDao = session.getMapper(EmployeeDao.class);
            try{
                   int size = employees.size();
                   for(int i = 0; i< size ;i++){
                        Employee employee = employees.get(i);
                //这下面这里调用这个方法的时候,在批处理的操作语境下等价于调用 prepareStatement.addBatch()
                        employeeDao.update(employee);
                //这个if判断是避免积累太多的更新数据造成堆栈溢出的现象
                        if(i>0 && i%2 ==0 || i ==size-1){
                  //等价于调用prepareStatement的executeBatch方法
                            session.commit();  
                                //调用commit的时候,其内部真正完成批量操作的方法其实是 flushStatement();这个方法的返回值可以获取
                               //每个更新语句影响的行数,这个数据 flushStatements()方法不会自动调用clearCache()方法来清理一级缓存
                               //但是调用commit这个方法的时候,会自动调用清空内部一级缓存的方法
    
                        }
                    }
                }catch(Exception e){
                    session.rollback();
                }finally{
                    session.close();
                }
        }
    }
  • 相关阅读:
    几个常用排序的代码实现堆排序|快排|归并排序 Marathon
    0647回文子串 Marathon
    任意输入一个日期输出是当年的第几天星期几
    从输入URL到浏览器显示页面发生了什么
    常用链接整理
    computed 与 method
    将博客搬至CSDN
    leetcode_Two Sum
    VC++6.0与Office2010冲突解决方案
    C&C++_malloc函数
  • 原文地址:https://www.cnblogs.com/LixiaoFeng1650062546/p/11656710.html
Copyright © 2020-2023  润新知