精华内容
下载资源
问答
  • Mybatis批量插入

    2016-09-29 14:12:39
    Mybatis批量插入

    最近做一个批量导入的需求,将多条记录批量插入数据库中。解决思路:在程序中封装一个List集合对象,然后把该集合中的实体插入到数据库中,因为项目使用了MyBatis,所以打算使用MyBatis的foreach功能进行批量插入。期间遇到了“SQL 命令未正确结束 ”的错误,最终解决,记录下来供以后查阅和学习。

            首先,在网上参考了有关Mybatis的foreach insert的资料,具体如下:

            foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。

            foreach元素的属性主要有 item,index,collection,open,separator,close。

            item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束,在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:

            1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list

            2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array

            3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map

            然后,照葫芦画瓢写了如下的xml文件,

    xxxMapper.xml文件:

    <insert id="addSupCity" parameterType="java.util.List">
        <selectKey keyProperty="cityId" order="BEFORE" resultType="String">
            <![CDATA[SELECT SEQ_OCL_SUPCITY.NEXTVAL FROM dual]]>
        </selectKey>
        INSERT INTO T_OCL_SUPCITY
        (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT)
        VALUES 
        <foreach collection="list" item="item" index="index" separator=",">     
          (
            #{item.cityId,jdbcType=VARCHAR},
            #{item.cityCode,jdbcType=VARCHAR},
            #{item.cityName,jdbcType=VARCHAR},
            #{item.areaDesc,jdbcType=VARCHAR},
            #{item.supId,jdbcType=VARCHAR},
            #{item.stat,jdbcType=VARCHAR}
          )
        </foreach>
    </insert>

            但是运行起来后就一直报错,报错信息如下:

    ### SQL: INSERT INTO T_OCL_SUPCITY
    (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?)
    ### Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正确结束

            把SQL复制出来在PL/SQL中运行也是报同样的错,如上也可以看出,使用批量插入执行的SQL语句等价于: INSERT INTO T_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?),而在oracle中用insert into xxx values (xxx,xxx),(xxx,xxx) 这种语法是通不过的 。再回过头去看那篇文章,发现这是适用于MySQL的,不适用于Oracle,因此把xml文件修改一下:

    <insert id="addSupCity" parameterType="java.util.List">
          INSERT INTO T_OCL_SUPCITY
      (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT)
    SELECT SEQ_OCL_SUPCITY.NEXTVAL CITY_ID, A.*
    FROM(
    <foreach collection="list" item="item" index="index" separator="UNION ALL">
     SELECT 
           #{item.cityCode,jdbcType=VARCHAR} CITY_CODE,
           #{item.cityName,jdbcType=VARCHAR} CITY_NAME,
           #{item.areaDesc,jdbcType=VARCHAR} AREA_DESC,
           #{item.supId,jdbcType=VARCHAR} SUP_ID,
           #{item.stat,jdbcType=VARCHAR} STAT
         FROM dual
       </foreach>
       )A
      </insert>

            运行通过。在Oracle的版本中,有几点需要注意的:

            1.SQL中没有VALUES;

            2.<foreach>标签中的(selece ..... from dual);

            3.<foreach>标签中的separator的属性为"UNION ALL",将查询合并结果集。

    展开全文
  • mybatis批量插入

    2019-12-17 09:58:50
    链接:mybatis批量插入
    展开全文
  • mybatis 批量插入

    2020-09-18 17:22:45
    mybatis 批量插入有三种,下面这种效率最好,其它的太慢 批量插入 1:批量 循环的参数 acctdefconfigs;对应是一个list void batchInsertAcctdeferconfigs(@Param(“acctdefconfigs”) List acctdeferconfigs); 2:...

    mybatis 批量插入有三种,下面这种效率最好,其它的太慢

    批量插入

    1:批量 循环的参数 acctdefconfigs;对应是一个list
    void batchInsertAcctdeferconfigs(@Param(“acctdefconfigs”) List acctdeferconfigs);

    2:parameterType=“map”
    3:注意insert的参数和foreach参数对应的名字

    insert into cb_loan_acctdeferconfig (
    acctnbr,
    balcatcd,
    baltypcd,
    shardingkey,
    defertranamt,
    startdate,
    enddate,
    defercalperiodcd,
    totalcount,
    nextdeferdate,
    defercount,
    origamt,
    deferredamt,
    deferbalamt,
    reversalyn,
    termnbr
    )
    5:foreach collection是传入的list(@Param) item 是个别名

    (
    #{item.acctnbr},
    #{item.balcatcd},
    #{item.baltypcd},
    #{item.shardingkey},
    #{item.defertranamt},
    #{item.startdate},
    #{item.enddate},
    #{item.defercalperiodcd},
    #{item.totalcount},
    #{item.nextdeferdate},
    #{item.defercount},
    #{item.origamt},
    #{item.deferredamt},
    #{item.deferbalamt},
    #{item.reversalyn},
    #{item.termnbr}
    )

    展开全文
  • Mybatis 批量插入

    2017-05-11 11:18:12
    Mybatis 批量插入、存储过程
    2013三月
    28

    Mybatis 批量插入、存储过程

    本文地址,转载注明出处:http://www.cnblogs.com/sunwufan/archive/2012/04/27/2473308.html

    本文将详细讲解Mybatis访问MySQL数据库的三种方式及测试效果。

    三种方式:simple方式(基本数据库逐条访问)、batch方式(批量操作)、procedure方式(存储过程)。

    文章主要内容:

    • 准备工作:数据库建立、存储过程建立等。
    • Eclipse中的项目搭建。
    • 所得数据分析,工作原理浅析。

     

    1.准备工作:

     

        命令行还是图形界面?这个随意,总之建完就这么个东西。

          

    建表主要有两点注意:

    • 主键要自增(再插入数据是时,省去很多麻烦)
    • 表要建成UTF8格式(否则插入中文可能报错,或乱码。当然在安装MySQL进行配置时也要选GBK之类的)

    为MySQL建存储过程

     

    MySQL存储过程代码
    复制代码
     1 CREATE DEFINER = `root`@`localhost` PROCEDURE `NewProc`(IN `name_in` varchar(255),IN `age_in` int,IN `sex_in` varchar(255),IN `password_in` varchar(255),IN `num_in` int)
     2 BEGIN
     3     SET @a=0;
     4 Label:LOOP
     5     SET @a=@a+1;
     6     INSERT INTO person ( name, age, sex, password) VALUES (name_in,age_in,sex_in,password_in);
     7      IF @a=num_in THEN
     8             LEAVE Label;
     9         END IF;
    10 END LOOP Label;
    11 END;
    复制代码

          num_in为执行插入操作的次数,在java中设好,传入。

         不管什么方式,最终效果一样就可进入下一步。

         本文地址,转载注明出处:Mybatis 批量插入、存储过程

     

    2.Eclipse中的项目搭建。

      建立javaProject,最终目录结构。

    简单说下建立时的逻辑顺序:1导入三个jar包–>2建立log4j.properties –>3建立Configuration.xml–>4建立Person.java–>5 建立InsertSimple.java–>6建立person.xml–>7在Configuration.xml中注册person.xml–>此时InsertSimple.java就可以运行了。

    剩下的两个Insert**.java建立好后在person.xml中注入即可。

    ok讲完流程了,下面开始狂贴代码:

      配置文件

    Configuration.xml
    复制代码
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
     3 <configuration>
     4     <environments default="myexample">
     5         <environment id="myexample">
     6             <transactionManager type="JDBC" />
     7             <dataSource type="POOLED">
     8                 <property name="driver" value="com.mysql.jdbc.Driver" />
     9                 <property name="url" value="jdbc:mysql://localhost:3306/javaweb" />
    10                 <property name="username" value="root" />
    11                 <property name="password" value="admin"/>
    12             </dataSource>
    13         </environment>
    14     </environments>
    15     <mappers>
    16         <mapper resource="person.xml"/>
    17     </mappers>
    18 </configuration>
    复制代码

    log4j.properties
    复制代码
     1 log4j.rootLogger=DEBUG, Console
     2 
     3 #Console
     4 log4j.appender.Console=org.apache.log4j.ConsoleAppender
     5 log4j.appender.Console.layout=org.apache.log4j.PatternLayout
     6 log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
     7 
     8 log4j.logger.java.sql.ResultSet=INFO
     9 log4j.logger.org.apache=INFO
    10 log4j.logger.java.sql.Connection=DEBUG
    11 log4j.logger.java.sql.Statement=DEBUG
    12 log4j.logger.java.sql.PreparedStatement=DEBUG  
    复制代码

    person.xml
    复制代码
     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
     3 <mapper namespace="org.wufan.dao.PersonDao">
     4 
     5 
     6     <insert id="insert" parameterType="org.wufan.vo.Person"
     7         keyProperty="id" keyColumn="GENERATED_KEY" useGeneratedKeys="true">
     8         INSERT INTO person ( name, age, sex, password)
     9         VALUES (
    10         #{name},#{age},#{sex},#{password} )
    11     </insert>
    12 
    13 
    14     <insert id="insertBatch" parameterType="org.wufan.vo.Person"
    15         keyProperty="id" keyColumn="GENERATED_KEY" useGeneratedKeys="true">
    16         INSERT INTO person ( name, age, sex, password)
    17         VALUES
    18         <foreach collection="persons" item="item" index="index"
    19             separator=",">
    20             (#{item.name},#{item.age},#{item.sex},#{item.password})
    21         </foreach>
    22     </insert>
    23 
    24 
    25     <insert id="insertByProc" statementType="CALLABLE">
    26         {call insertPro(#{name},#{age},#{sex},#{password},#{num})}
    27     </insert>
    28 
    29 </mapper>
    复制代码

      Java代码

       pojo(vo)类

    Person.java
    复制代码
     1 package org.wufan.vo;
     2 
     3 
     4 public class Person {
     5     private int id;
     6     private String name;
     7     private int age;
     8     private String sex;
     9     private String password;
    10     public int getId() {
    11         return id;
    12     }
    13     public void setId(int id) {
    14         this.id = id;
    15     }
    16     public String getName() {
    17         return name;
    18     }
    19     public void setName(String name) {
    20         this.name = name;
    21     }
    22     public int getAge() {
    23         return age;
    24     }
    25     public void setAge(int age) {
    26         this.age = age;
    27     }
    28     public String getSex() {
    29         return sex;
    30     }
    31     public void setSex(String sex) {
    32         this.sex = sex;
    33     }
    34     public String getPassword() {
    35         return password;
    36     }
    37     public void setPassword(String password) {
    38         this.password = password;
    39     }
    40 }
    复制代码

      

      普通方式(for循环逐条插入)的主函数

    InsertSimple.java
    复制代码
     1 package org.wufan.test;
     2 
     3 import java.io.IOException;
     4 import org.apache.ibatis.io.Resources;
     5 import org.apache.ibatis.session.SqlSession;
     6 import org.apache.ibatis.session.SqlSessionFactory;
     7 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
     8 import org.wufan.vo.Person;
     9 
    10 public class InsertSimple {
    11 
    12     /**
    13      * @param args
    14      */
    15     public static void main(String[] args) {
    16 
    17         int num = 10000;// 插入数据量
    18         SqlSessionFactory factory = null;
    19         try {
    20             factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("Configuration.xml"));
    21         } catch (IOException e) {
    22             e.printStackTrace();
    23         }
    24         System.out.println("进入MySQL");
    25         double begin = System.currentTimeMillis();
    26         SqlSession sqlSession = factory.openSession();
    27         Person per = new Person();
    28         for (int i = 1; i <= num; i++) {
    29 
    30             per.setName("InsertSimple" + i);
    31             per.setAge(i);
    32             per.setSex("男");
    33             per.setPassword("密码" + i);
    34 
    35             sqlSession.insert("org.wufan.dao.PersonDao.insert", per);
    36             sqlSession.commit();
    37             // sqlSession.clearCache();
    38         }
    39         double time = (System.currentTimeMillis() - begin) / 1000;
    40         System.out.println("插入共花费时间" + time + "s");
    41     }
    42 
    43 }
    复制代码

     

      batch方式(批量操作)的主函数

    InsertBatch。java
    复制代码
     1 package org.wufan.test;
     2 
     3 import java.io.IOException;
     4 import java.util.ArrayList;
     5 import java.util.HashMap;
     6 import java.util.List;
     7 import java.util.Map;
     8 
     9 import org.apache.ibatis.io.Resources;
    10 import org.apache.ibatis.session.ExecutorType;
    11 import org.apache.ibatis.session.SqlSession;
    12 import org.apache.ibatis.session.SqlSessionFactory;
    13 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    14 import org.wufan.vo.Person;
    15 
    16 public class InsertBatch {
    17 
    18     /**
    19      * @param args
    20      */
    21     public static void main(String[] args) {
    22 
    23         int num = 10000;// 插入数据量
    24         SqlSessionFactory factory = null;
    25         List<Person> list = new ArrayList<Person>();
    26         try {
    27             factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("Configuration.xml"));
    28         } catch (IOException e) {
    29             e.printStackTrace();
    30         }
    31         Person per = new Person();
    32         for (int i = 1; i <= num; i++) {
    33             // per.setId(null);
    34             per.setName("InsertBatchName" + i);
    35             per.setAge(i);
    36             per.setSex("男");
    37             per.setPassword("密码" + i);
    38             list.add(per);
    39         }
    40         double begin = System.currentTimeMillis();
    41         SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false);
    42 
    43         Map<String, List<Person>> tmp = new HashMap<String, List<Person>>();
    44         tmp.put("persons", list);
    45 
    46         sqlSession.insert("org.wufan.dao.PersonDao.insertBatch", tmp);
    47         sqlSession.commit();
    48 
    49         sqlSession.close();
    50         double time = (System.currentTimeMillis() - begin) / 1000;
    51         System.out.println("插入共花费时间" + time + "s");
    52 
    53     }
    54 }
    复制代码

     

        procedure方式(存储过程)的主函数

    InsertProcedure。java
    复制代码
     1 package org.wufan.test;
     2 
     3 import java.io.IOException;
     4 import java.util.HashMap;
     5 import java.util.Map;
     6 
     7 import org.apache.ibatis.io.Resources;
     8 import org.apache.ibatis.session.SqlSession;
     9 import org.apache.ibatis.session.SqlSessionFactory;
    10 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    11 
    12 public class InsertProcedure {
    13 
    14     /**
    15      * @param args
    16      */
    17     public static void main(String[] args) {
    18         int num=10000;//插入数据量
    19         SqlSessionFactory factory = null;
    20         ;
    21         try {
    22             factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("Configuration.xml"));
    23         } catch (IOException e) {
    24             e.printStackTrace();
    25         }
    26         SqlSession sqlSession = factory.openSession();
    27         Map map = new HashMap();
    28         map.put("name", "InsertProcName");
    29         map.put("age", 11);
    30         map.put("sex", "男");
    31         map.put("password", "1234");
    32         map.put("num", num);
    33         double begin = System.currentTimeMillis();
    34         sqlSession.insert("org.wufan.dao.PersonDao.insertByProc", map);
    35         sqlSession.commit();
    36         sqlSession.close();
    37         double time = (System.currentTimeMillis() - begin) / 1000;
    38         System.out.println("插入共花费时间" + time + "s");
    39     }
    40 }
    复制代码

     

          三种方式的控制台log

     

          普通方式InsertSimple.java

         

    batch方式(批量操作)

     

    procedure方式(存储过程)

    如果出现以上三图,恭喜,哥们你成功了!!

     

    3.所得数据分析。

    复制代码
     1     1--num = 1000 ;  
     2        普通处理:3.527s
     3        批量处理:0.628s  
     4        存储过程处理:0.144s
     5       
     6     2--num = 1w;  
     7        普通处理:27.465s  
     8        批量处理:1.528s  
     9        存储过程处理:0.585s  
    10       
    11     3--num = 10w;  
    12        普通处理: 335.18s  
    13        批量处理: 11.944s
    14        存储过程处理:5.146s  
    15       
    16     4--num = 30w;  
    17        普通处理: 885.335s     
    18        批量处理:34.767s
    19       存储过程处理:15.875s
    复制代码

     小笔记本扛不住了,测试就到这里了。

     注意:在这里由于存储数据过大,批量处理时内存会吃不消。

    • 我的笔记本到达10W条数据时,会超过MySQL默认内存设置。Eclipse会报错。

       解决办法:http://www.cnblogs.com/chy710/archive/2008/03/06/1093680.html

    当插入30w条数据时会报“Java heap space” java虚拟机内存错误

       解决办法:http://developer.51cto.com/art/200906/128572.htm

     

       工作原理浅析(其实上面的DEBUG截图,已经很能说明问题了):

    • 普通方式,就是一条一条往里插。

      优点:对计算机基本没什么要求,插入方式灵活。

      缺点:重复插入大量数据时,很慢。

    • 批量处理:是把插入请求放入内存,一起提交给数据库。

      优点:比普通方式快,比存储过程灵活。

      缺点:吃内存,海量数据压力略大。

    • 存储过程:只需在程序中调用存储过程,向数据库传参,。数据库根据你建好的存储过程来跑。

      优点:最快,飞起啊!!

      缺点:较为死板,换数据库工具,还要在新的数据库中建立存储过程。改需求时维护,较为麻烦。

          从数据报告可看出,普通插入理论上就是一次函数,二阶导数为零(就尼玛直线啊!);批量处理和存储过程应该都是会有一个性价比最好的值。一阶导数恒大于零,二阶导数先正后负。

     

    PS:

    •  Mybatis和Ibatis还是有些不同的(虽然没用过Ibatis),网上的文章比较少,官网的用户报告下不下来,靠网友经验和自己摸索做的。本人也是被赶鸭子上架头一次做,之前都怎么敲过java代码,更别说框架了,如有错误请指正!!
    • 请不要管我要源码了,这些写的比较清楚了(基本上这就算源码了==!),用源码一点成就感都没得。
    •  别问我其他操作怎么搞,我估计也不会的,如果针对此教程调试不通过可以尽管问。

          

    最后是查到的一些对我有帮助的资料:

           ibatis 学习笔记(一) 批量处理 存储过程 (行文方式直接抄他的,但具体技术就不一样了,他的测试结果有点怪)

       Mybatis调用存储过程  ibatis3调用存储过程  mybatis 3.0.5 –batch insert后如何获取返回的值

          
    MyBatis的关于批量数据操作的体会
     Java:MyBatis简单入门   MyBatis简介与配置MyBatis+Spring+MySql 





    展开全文
  • MyBatis批量插入

    2017-04-14 20:13:00
    MyBatis批量插入 学习了:http://chenzhou123520.iteye.com/blog/1583407/  
  • MyBatis 批量插入

    2021-01-29 07:56:21
    拼接批量 insert SQL 脚本 1、Maven 依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/PO.
  • Mybatis 批量插入数据

    2020-01-07 21:31:09
    mybatis 批量插入

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,902
精华内容 1,560
关键字:

mybatis批量插入