假设需要批量插入10000条实体数据至数据库。如下是各个操作方法及耗时

环境Spring boot

1、JDBC(JdbcTemplate)
pom.xml
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-jdbc</artifactId>
  4. </dependency>
Service
  1. @Autowired
  2. private JdbcTemplate jdbcTemplate;
  3. public void jdbc(List<String> list){
  4. int[] updatedCountArray=jdbcTemplate.batchUpdate("INSERT INTO customer (name) VALUES (?);", new BatchPreparedStatementSetter() {
  5. @Override
  6. public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
  7. preparedStatement.setString(1,list.get(i));
  8. }
  9. @Override
  10. public int getBatchSize() {
  11. return list.size();
  12. }
  13. });
  14. }

2、网上最常见的JPA----entityManager批量操作方法
Entity
  1. package net.xjdsz.model;
  2. import javax.persistence.*;
  3. /**
  4. * Created by dingshuo on 2017/6/23.
  5. */
  6. @Entity
  7. @Table(name = "customer", schema = "test", catalog = "")
  8. public class CustomerEntity {
  9. private int id;
  10. private String name;
  11. @Id
  12. @GeneratedValue(strategy = GenerationType.AUTO)
  13. @Column(name = "id", nullable = false)
  14. public int getId() {
  15. return id;
  16. }
  17. public void setId(int id) {
  18. this.id = id;
  19. }
  20. @Basic
  21. @Column(name = "name", nullable = true, length = 100)
  22. public String getName() {
  23. return name;
  24. }
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28. @Override
  29. public boolean equals(Object o) {
  30. if (this == o) return true;
  31. if (o == null || getClass() != o.getClass()) return false;
  32. CustomerEntity that = (CustomerEntity) o;
  33. if (id != that.id) return false;
  34. if (name != null ? !name.equals(that.name) : that.name != null) return false;
  35. return true;
  36. }
  37. @Override
  38. public int hashCode() {
  39. int result = id;
  40. result = 31 * result + (name != null ? name.hashCode() : 0);
  41. return result;
  42. }
  43. }
Service
  1. private EntityManager em;
  2. @PersistenceContext(name = "EntityManagerFactory")
  3. public void SetEntityManager(EntityManager em) {
  4. this.em = em;
  5. }
  6. @Transactional
  7. public void saveBatch(List<CustomerEntity> list) {
  8. for (int i = 0; i < 10000; i++) {
  9. em.persist(list.get(i));
  10. if (i % 1000 == 0) {
  11. em.flush();
  12. em.clear();
  13. }
  14. }
  15. }

3、Jpa---Repository循环写入
Repository
  1. package net.xjdsz.dao;
  2. import net.xjdsz.model.CustomerEntity;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. import org.springframework.stereotype.Repository;
  5. /**
  6. * Created by dingshuo on 2017/6/23.
  7. */
  8. @Repository
  9. public interface CustomerRepository extends JpaRepository<CustomerEntity,Integer> {
  10. }

4、Jpa--Repository批量写入
Service
  1. @Transactional
  2. public void saveBatchJpa(List<CustomerEntity> list) {
  3. repository.save(list);
  4. }

实验代码:
用的是Spring boot,所以开了一个RestController去做实验
  1. package net.xjdsz;
  2. import net.xjdsz.dao.CustomerRepository;
  3. import net.xjdsz.dao.TestService;
  4. import net.xjdsz.model.CustomerEntity;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.web.bind.annotation.GetMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /**
  11. * Created by dingshuo on 2017/6/23.
  12. */
  13. @RestController
  14. public class TestController {
  15. @Autowired
  16. TestService service;//测试用的Service类
  17. @Autowired
  18. CustomerRepository repository; //实体Repository接口
  19. @GetMapping(value = "/test")
  20. public void test(){
  21. List<String> list=new ArrayList<>(); //给jdbctemplate用的集合
  22. List<CustomerEntity> customerEntityList=new ArrayList<>();//给jpa用的集合
  23. for(int i=0;i<10000;i++){
  24. list.add("学生"+i);
  25. CustomerEntity customerEntity=new CustomerEntity();
  26. customerEntity.setName("学生"+i);
  27. customerEntityList.add(customerEntity);
  28. }
  29. //1.jdbc
  30. long startTime=System.currentTimeMillis(); //获取开始时间
  31. service.jdbc(list);
  32. long endTime=System.currentTimeMillis(); //获取结束时间
  33. System.out.println("jdbc程序运行时间: "+(endTime-startTime)+"ms");
  34. //2.jpa-em
  35. long startTime1=System.currentTimeMillis(); //获取开始时间
  36. service.saveBatch(customerEntityList);
  37. long endTime1=System.currentTimeMillis(); //获取结束时间
  38. System.out.println("JPA-EM程序运行时间: "+(endTime1-startTime1)+"ms");
  39. //3.jpa-循环
  40. long startTime2=System.currentTimeMillis(); //获取开始时间
  41. for(int i=0;i<customerEntityList.size();i++){
  42. repository.save(customerEntityList.get(i));
  43. }
  44. long endTime2=System.currentTimeMillis(); //获取结束时间
  45. System.out.println("JPA-循环程序运行时间: "+(endTime2-startTime2)+"ms");
  46. //4.jpa-集合
  47. long startTime3=System.currentTimeMillis(); //获取开始时间
  48. repository.save(customerEntityList);
  49. long endTime3=System.currentTimeMillis(); //获取结束时间
  50. System.out.println("JPA-集合程序运行时间: "+(endTime3-startTime3)+"ms");
  51. }
  52. }

实验结果
  1. jdbc程序运行时间: 878ms
  2. JPA-EM程序运行时间: 2018ms
  3. JPA-循环程序运行时间: 21915ms
  4. JPA-集合程序运行时间: 2373ms

结论就是如果追求极致的性能(批量操作速度),优选JDBC。EM和JPA直接操作集合没有太大的性能区别,这对于新接触Spring JPA(比如我)的人来说,不比纠结有时候没法注入EM,直接使用JPA操作集合即可。
JPA的循环造作相当于对单条insert重复了10000遍,自然最慢,也不推荐了。

如下是JPA操作集合的代码,可以看出起始内部也是用的em,所以可以放心大胆的用了。
  1. @Transactional
  2. public <S extends T> List<S> save(Iterable<S> entities) {
  3. List<S> result = new ArrayList<S>();
  4. if (entities == null) {
  5. return result;
  6. }
  7. for (S entity : entities) {
  8. result.add(save(entity));
  9. }
  10. return result;
  11. }
  12. /*
  13. * (non-Javadoc)
  14. * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
  15. */
  16. @Transactional
  17. public <S extends T> S save(S entity) {
  18. if (entityInformation.isNew(entity)) {
  19. em.persist(entity);
  20. return entity;
  21. } else {
  22. return em.merge(entity);
  23. }
  24. }

JPA批量操作及性能比对的更多相关文章

  1. jpa batch批量操作save和persist比较

    1.网上最常见的JPA----entityManager批量操作方法 private EntityManager em; @PersistenceContext(name = "Entity ...

  2. 深入浅出学Spring Data JPA

    第一章:Spring Data JPA入门 Spring Data是什么 Spring Data是一个用于简化数据库访问,并支持云服务的开源框架.其主要目标是使得对数据的访问变得方便快捷,并支持map ...

  3. JPA基础

    目录 目录 1 一.JPA基础 2 1.1 JPA基础 2 1.2JPA开发过程 3 1.3 实体的生命周期及实体管理器常用方法 4 二.环境搭建 5 2.1 添加JPA支持 6 2.2 添加配置文件 ...

  4. Spring Data Jpa配置

    Spring Data JPA提供的接口,也是Spring Data JPA的核心概念: 1:Repository:最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组 ...

  5. JPA && Spring Data && Spring Data JPA

    1.JPA  Java Persistence API,用于对象持久化的一组API,JPA本身是一组规范,让开发者用同一种方式访问不同的ORM框架.其实也就是java实体对象和关系型数据库建立起映射关 ...

  6. JPA学习笔记

    一.JPA基础1.1 JPA基础JPA: java persistence api 支持XML.JDK5.0注解俩种元数据的形式,是SUN公司引入的JPA ORM规范 元数据:对象和表之间的映射关系 ...

  7. Spring Boot 系列教程2-Data JPA

    Spring Data JPA 用来简化创建 JPA 数据访问层和跨存储的持久层功能. 官网文档连接 http://docs.spring.io/spring-data/jpa/docs/curren ...

  8. Spring Data JPA 入门Demo

    什么是JPA呢? 其实JPA可以说是一种规范,是java5.0之后提出来的用于持久化的一套规范:它不是任何一种ORM框架,在我看来,是现有ORM框架在这个规范下去实现持久层. 它的出现是为了简化现有的 ...

  9. Spring Data JPA 初体验

    一,JPA相关的概念 JPA概述 全称是:JavaPersistence API.是SUN公司推出的一套基于ORM的规范. Hibernate框架中提供了JPA的实现. JPA通过JDK 5.0注解或 ...

随机推荐

  1. python基础知识--标志位的设定

    在单层循环的退出中,使用break即能退出,那么多层循环呢?机智的人们使用flag标识符的方式,例如: exit_flag = False for i in range(10): if i <5 ...

  2. Redis-cli 命令不能用

    bash: redis-cli: command not found... 环境: Linux7.X 在运行redis-cli命令的时候提示错误: 解决方案: 1. wget http://downl ...

  3. fc_net.py cs231n

    n如果有错误,欢迎指出,不胜感激 import numpy as np from cs231n.layers import * from cs231n.layer_utils import * cla ...

  4. Python 使用BeautifulSoup模块抽取数据

  5. 【JZOJ4792】【NOIP2016提高A组模拟9.21】整除

    题目描述 麦克雷有一个1~n的排列,他想知道对于一些区间,有多少对区间内的数(x,y),满足x能被y整除. 输入 第一行包含2个正整数n,m.表示有n个数,m个询问. 接下来一行包含n个正整数,表示麦 ...

  6. Directx11教程(21) 修正程序最小化异常bug

    原文:Directx11教程(21) 修正程序最小化异常bug       很长时间竟然没有注意到,窗口最小化时候,程序会异常,今天调试水面程序时,随意间最小化了窗口,发现程序异常了.经过调试,原来程 ...

  7. httpclient向浏览器发送get和post请求

    get请求代码实现 public static void main(String[] args) { CloseableHttpClient httpClient = null;  //请求对象 Cl ...

  8. springboot thymeleaf【转】【补】

    thymeleaf模板 https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html 1.引入thymeleaf依赖 <!-- ...

  9. bzoj4152 The Captain

    Description 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. Input 第一行包含一个正整数n(2 ...

  10. [牛腩]如何关闭.net framework4.0的请求验证 标签: 发布 2015-07-31 09:27 887人阅读 评论(38)

    敲牛腩的时候,点击运行提示:从客户端中检测到有潜在危险的 Request.Form 值,感觉自己代码敲的并没有问题,于是开始各种查,下面分享一下我对此进行的研究. 为什么会报这个错误? 在 Web 应 ...