• 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. }





  • 相关阅读:
    梯度下降
    Azure Blob数据迁移工具
    基于物理文件的HBase备份还原
    基于Azure Blob冷存储的数据压缩备份总结
    项目部署、配置、查错常用到的Linux命令
    阿里云服务器云数据库免费体验(Java Web详细实例)
    Linux文件编辑命令详细整理
    深入Java虚拟机(4)——网络移动性
    C#删除WebBrowser控件的Session
    深入Java虚拟机(3)——安全
  • 原文地址:https://www.cnblogs.com/tilv37/p/7070128.html
Copyright © 2020-2023  润新知