Mybatis 批量插入

来源:互联网 发布:云计算一般薪资多少 编辑:程序博客网 时间:2024/06/10 19:58
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=INFO10 log4j.logger.java.sql.Connection=DEBUG11 log4j.logger.java.sql.Statement=DEBUG12 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         VALUES18         <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 args14      */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 args20      */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 args16      */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.944s14        存储过程处理:5.146s  15       16     4--num = 30w;  17        普通处理: 885.335s     18        批量处理:34.767s19       存储过程处理: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 





0 0
原创粉丝点击