首先看下我们的目标:向mysql数据库中批量插入10000条数据
操作环境:mysql和java代码都运行在我本地windows电脑(i7处理器,4核,16g运行内存,64位操作系统
1、jpa单线程执行
代码省略,大概需要39s左右
2、jpa多线程执行
大概需要37s左右,并没有想象中的快很多
(免费学习视频分享:java视频教程)
原因: 多线程只是大大提高了程序处理数据的时间,并不会提高插入数据库的时间,相反在我这边jpa的框架下,多线程也就意味着多连接,反而更加消耗数据库性能
package com.example.demo.controller;import com.example.demo.entity.student;import com.example.demo.service.studentserviceinterface;import org.springframework.beans.factory.annotation.autowired;import org.springframework.web.bind.annotation.getmapping;import org.springframework.web.bind.annotation.requestmapping;import org.springframework.web.bind.annotation.restcontroller;import javax.xml.bind.validationexception;import java.util.arraylist;import java.util.date;import java.util.list;import java.util.concurrent.countdownlatch;import java.util.concurrent.executorservice;import java.util.concurrent.executors;@restcontroller@requestmapping("/student")public class studentcontroller { @autowired private studentserviceinterface studentserviceinterface; // 来使主线程等待线程池中的线程执行完毕 private countdownlatch threadssignal; // 每个线程处理的数据量 private static final int count = 1000; // 我的电脑为4核 线程池大小设置为2n+1 private static executorservice execpool = executors.newfixedthreadpool(9); /** * 多线程保存 * * @return * @throws validationexception */ @getmapping() public string savestudentenablethread() throws validationexception { long begin = new date().gettime(); // 需要插入数据库的数据 list<student> list = new arraylist<>(); for (int i = 0; i < 10000; i++) { student student = new student(); student.setname("张三"); student.setage(10); list.add(student); } try { if (list.size() <= count) { threadssignal = new countdownlatch(1); execpool.submit(new insertdate(list)); } else { list<list<student>> lists = dealdata(list, count); threadssignal = new countdownlatch(lists.size()); for (list<student> students : lists) { execpool.submit(new insertdate(students)); } } threadssignal.await(); } catch (exception e) { system.out.println(e.tostring() + " 错误所在行数:" + e.getstacktrace()[0].getlinenumber()); } // 结束时间 long end = new date().gettime(); return "10000条数据插入花费时间 : " + (end - begin) / 1000 + " s"; } /** * 数据组装 * 把每个线程要处理的数据 再组成一个list * 我这边就是把10000条数据 组成 10个1000条的集合 * * @param target 数据源 * @param size 每个线程处理的数量 * @return */ public static list<list<student>> dealdata(list<student> target, int size) { list<list<student>> threadlist = new arraylist<list<student>>(); // 获取被拆分的数组个数 int arrsize = target.size() % size == 0 ? target.size() / size : target.size() / size + 1; for (int i = 0; i < arrsize; i++) { list<student> students = new arraylist<student>(); //把指定索引数据放入到list中 for (int j = i * size; j <= size * (i + 1) - 1; j++) { if (j <= target.size() - 1) { students.add(target.get(j)); } } threadlist.add(students); } return threadlist; } /** * 内部类,开启线程批量保存数据 */ class insertdate extends thread { list<student> list = new arraylist<student>(); public insertdate(list<student> students) { list = students; } public void run() { try { // 与数据库交互 studentserviceinterface.save(list); threadssignal.countdown(); } catch (validationexception e) { e.printstacktrace(); } } }}
3、传统jdbc插入
大概需要8s左右,相较于前两种方式已经快很多了,代码如下:
package com.example.demo.controller;import org.springframework.web.bind.annotation.getmapping;import org.springframework.web.bind.annotation.requestmapping;import org.springframework.web.bind.annotation.restcontroller;import javax.xml.bind.validationexception;import java.sql.connection;import java.sql.drivermanager;import java.sql.preparedstatement;import java.util.date;@restcontroller@requestmapping("/student1")public class studentcontroller1 { @getmapping() public string savestudentenablethread() throws validationexception { // 开始时间 long begin = new date().gettime(); connection connection = null; try { connection = drivermanager.getconnection("jdbc:mysql://localhost:3306/db01?characterencoding=utf8&useunicode=true&usessl=false&servertimezone=utc&allowpublickeyretrieval=true", "admin", "123456");//获取连接 if (connection != null) { system.out.println("获取连接成功"); } else { system.out.println("获取连接失败"); } //这里必须设置为false,我们手动批量提交 connection.setautocommit(false); //这里需要注意,sql语句的格式必须是预处理的这种,就是values(?,?,...,?),否则批处理不起作用 preparedstatement statement = connection.preparestatement("insert into student(id,`name`,age) values(?,?,?)"); // 塞数据 for (int i = 0; i < 10000; i++) { statement.setint(1, i+1); statement.setstring(2, "张三"); statement.setint(3, 10); //将要执行的sql语句先添加进去,不执行 statement.addbatch(); } // 提交要执行的批处理,防止 jdbc 执行事务处理 statement.executebatch(); connection.commit(); // 关闭相关连接 statement.close(); connection.close(); } catch (exception e) { e.printstacktrace(); } // 结束时间 long end = new date().gettime(); // 耗时 system.out.println("10000条数据插入花费时间 : " + (end - begin) / 1000 + " s"); return "10000条数据插入花费时间 : " + (end - begin) / 1000 + " s"; }}
4、最后检查一下数据是否成功存库,一共30000条,没有丢数据
完成!
相关推荐:java入门教程
以上就是java向mysql数据库批量插入大量数据的详细内容。