zoukankan      html  css  js  c++  java
  • JPA批量操作及性能比对

    假设需要批量插入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. }





  • 相关阅读:
    LeetCode 275. H-Index II
    LeetCode 274. H-Index
    LeetCode Gray Code
    LeetCode 260. Single Number III
    LeetCode Word Pattern
    LeetCode Nim Game
    LeetCode 128. Longest Consecutive Sequence
    LeetCode 208. Implement Trie (Prefix Tree)
    LeetCode 130. Surrounded Regions
    LeetCode 200. Number of Islands
  • 原文地址:https://www.cnblogs.com/tilv37/p/7070128.html
Copyright © 2011-2022 走看看