zoukankan      html  css  js  c++  java
  • Mybatis-批量执行

    一、使用动态SQL 中的 Foreach 批量插入

    1.MySQL

    // 实体类
    
    public class MyUser {
        private Integer id;
        private String name;
        private Integer age;
        private Dept dept;
    
    
    public class Dept {
        private Integer id;
        private String name;
        private List<MyUser> myUsers;

    SQL

    <!-- 一条 SQL -->
    <!--public Boolean addMyUsers(@Param("users") List<MyUser> users);-->
    <insert id="addMyUsers">
        insert into myuser(name,age,did) values
        <foreach collection="users" item="user" separator=",">
          (#{user.name},#{user.age},#{user.dept.id})
        </foreach>
    </insert>
    
    <!-- 多条 SQL -->
    <!-- 一次执行多条 SQL 需在 JDBC 数据库连接属性添加 allowMultiQueries=true -->
    <!--public Boolean addMyUsers(List<MyUser> users);-->
    <insert id="addMyUsers">
        <foreach collection="list" item="user" separator=";">
            insert into myuser(name,age,did) values (#{user.name},#{user.age},#{user.dept.id})
        </foreach>
    </insert>

    测试代码

    /**
     * driver=com.mysql.cj.jdbc.Driver
     * url=jdbc:mysql://192.168.8.136:3306/mybatis?allowMultiQueries=true
     * username=root
     * password=root
     */
    public static void main(String[] args) {
        SqlSession session = null;
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            session = sqlSessionFactory.openSession();
    
            MyUserMapper mapper = session.getMapper(MyUserMapper.class);
    
            Dept dept = new Dept(2,null);
            MyUser myUser1 = new MyUser(null,"xsa",34,dept);
            MyUser myUser2 = new MyUser(null,"fgb",24,dept);
            MyUser myUser3 = new MyUser(null,"wdx",18,dept);
            List<MyUser> list = new ArrayList<>();
            list.add(myUser1);
            list.add(myUser2);
            list.add(myUser3);
            mapper.addMyUsers(list);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    2.Oracle

    <!-- Oracle数据库批量保存,Oracle不支持 values(),(),()
        1、多个insert放在begin - end里面
            begin
                insert into employees(employee_id,last_name,email)
                values(employees_seq.nextval,'test_001','test_001@atguigu.com');
                insert into employees(employee_id,last_name,email)
                values(employees_seq.nextval,'test_002','test_002@atguigu.com');
            end;
        2、利用中间表:
            insert into employees(employee_id,last_name,email)
               select employees_seq.nextval,lastName,email from(
                      select 'test_a_01' lastName,'test_a_e01' email from dual
                      union
                      select 'test_a_02' lastName,'test_a_e02' email from dual
                      union
                      select 'test_a_03' lastName,'test_a_e03' email from dual
               ) -->
    <insert id="addEmps" databaseId="oracle">
        <!-- oracle第一种批量方式 -->
        <foreach collection="emps" item="emp" open="begin" close="end;">
            insert into employees(employee_id,last_name,email) values(employees_seq.nextval,#{emp.lastName},#{emp.email});
        </foreach>
    
        <!-- oracle第二种批量方式  -->
        insert into employees(employee_id,last_name,email)
        <foreach collection="emps" item="emp" separator="union" open="select employees_seq.nextval,lastName,email from(" close=")">
            select #{emp.lastName} lastName,#{emp.email} email from dual
        </foreach>
    </insert>
    <sql id="insertColumn">
        <if test="_databaseId=='oracle'">
            employee_id,last_name,email
        </if>
        <if test="_databaseId=='mysql'">
            last_name,email,gender,d_id
        </if>
    </sql>

    二、使用 Mybatis 的批量执行器

    1.单独使用

    public static void main(String[] args) {
        SqlSession session = null;
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 获取批量执行器,设置不自动提交(默认 false)
            session = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
    
            UserMapper mapper = session.getMapper(UserMapper.class);
            User user = new User();
    
            long start = System.currentTimeMillis();
            for (int i = 0; i < 1000; i++) {
                user.setName(UUID.randomUUID().toString());
                user.setAge(25);
                mapper.insertUser(user);
            }
            long end = System.currentTimeMillis();
    
            //批量:预编译sql一次 ==> 设置参数(1000次)===> 执行(1次)===> 执行时长:889
            //非批量:(预编译sql=设置参数=执行)(1000次) ===> 执行时长:8812
            System.out.println("执行时长:"+(end-start));
    
            // 使用 JDBC 事务需管理要手动提交事务
            session.commit();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    2.在 SSM 中使用

    首先给容器中添加一个可批量执行的 SqlSession,两种方式

    xml 方式

    <!--配置一个可以进行批量执行的sqlSession  -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg>
        <constructor-arg name="executorType" value="BATCH"></constructor-arg>
    </bean>

    代码方式

    /**
     * 配置一个可以进行批量执行的 sqlSession
     */
    @Bean
    public SqlSessionTemplate getSqlSessionTemplate(SqlSessionFactoryBean sqlSessionFactoryBean) throws Exception {
        /**
         * Simple Executor -- SIMPLE 普通的执行器,默认
         * Reuse Executor -执行器会重用预处理语句(prepared statements)
         * Batch Executor --批量执行器
         */
        SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean.getObject(), ExecutorType.BATCH);
        return sessionTemplate;
    }

    使用批量执行,在 service 中注入即可

    // @Autowired
    // private SqlSessionTemplate sqlSessionTemplate;
    @Autowired
    private SqlSession sqlSession;
    
    public List<Employee> getEmps(){
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        return employeeMapper.getEmps();
    }

    https://www.cnblogs.com/jhxxb/p/10451387.html

  • 相关阅读:
    C++
    复盘-2018.6.8~2020.6.8
    C++
    C++
    C++
    C++
    Python学习笔记(十)- 面向对象(一)
    SSHException: Error reading SSH protocol banner
    docker 安装mysql
    docker 安装部署
  • 原文地址:https://www.cnblogs.com/jhxxb/p/10737234.html
Copyright © 2011-2022 走看看