1: 项目里面使用springboo-boot-start-data-jpa操作数据库,通过源码,在repository上继承JpaRepository 可以实现保存操作,其中源码接口为:

  1. <S extends T> List<S> save(Iterable<S> var1);

从源码接口可以看出,其中已经提供批量保存接口,继续跟进实现类源码:

  1. @Transactional
  2. public <S extends T> List<S> save(Iterable<S> entities) {
  3. List<S> result = new ArrayList();
  4. if(entities == null) {
  5. return result;
  6. } else {
  7. Iterator var3 = entities.iterator();
  8.  
  9. while(var3.hasNext()) {
  10. S entity = var3.next();
  11. result.add(this.save(entity));
  12. }
  13.  
  14. return result;
  15. }
  16. }

从源码我们看出遍历集合,调用save()方法,我们跟进save方法

  1. @Transactional
  2. public <S extends T> S save(S entity) {
  3. if(this.entityInformation.isNew(entity)) {
  4. this.em.persist(entity);
  5. return entity;
  6. } else {
  7. return this.em.merge(entity);
  8. }
  9. }

主要就是判断这个对象数据库里面是否存在,如果存在则更新, 如果是不存在则新增;根据事务的传播性,在执行persist或者merge操作之后并不会直接提交事务。而是在所有循环保存之后@Transaction注解会统一flush,commit事务 ,下面介绍关于EntityManager常用API

JPA EntityManager 的四个主要方法---persist,merge,refresh,remove

  1. public void persist(Object entity);

persist 方法可以将实例转换为 managed( 托管 ) 状态。在调用 flush() 方法或提交事物后,实例将会被插入到数据库中。

  1. public <T> T merge(T entity);

merge 方法的主要作用是将用户对一个 detached 状态实体的修改进行归档,归档后将产生一个新的 managed 状态对象。

  1. public void refresh(Object entity);

refresh 方法可以保证当前的实例与数据库中的实例的内容一致。

  1. public void remove(Object entity);

remove 方法可以将实体转换为 removed 状态,并且在调用 flush() 方法或提交事物后删除数据库中的数据。

2: 第二种自己通过EntityManager 批量保存数据,下面直接贴代码了

  1. package com.sysware.cloud.dts.service;
  2.  
  3. import com.sysware.cloud.dts.dtcs.entity.DistributedTransactionEntity;
  4. import com.sysware.cloud.dts.model.DistributedTransaction;
  5. import com.sysware.cloud.dts.redis.client.DtsRedisClient;
  6. import com.sysware.cloud.sys.util.BeanUtil;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.stereotype.Service;
  10. import org.springframework.transaction.annotation.Transactional;
  11.  
  12. import javax.annotation.Resource;
  13. import javax.persistence.EntityManager;
  14. import java.util.List;
  15.  
  16. /**
  17. * Created by tianwenqing on 2018/7/4.
  18. */
  19. @Service
  20. @Transactional
  21. @Slf4j
  22. public class DistributeTransactionService {
  23.  
  24. @Autowired
  25. private EntityManager entityManager;
  26.  
  27. public void batchSave(List<DistributedTransaction> lst) {
  28. int j = 0;
  29. for (DistributedTransaction distributedTransaction : lst) {
  30. //TODO 判断数据的合法性
  31. entityManager.persist(distributedTransaction);
  32. j++;
  33. if (j % 50 == 0 || j == lst.size()) {
  34. try {
  35. entityManager.flush();
  36. }catch (Exception e){
  37. log.error("fail",e);
  38. }finally {
  39. entityManager.clear();
  40. }
  41.  
  42. }
  43.  
  44. }
  45. }
  46. }

上面的逻辑是批量插入很多数据,然后自己模拟50条flush一次,然后clear掉缓存,(防止缓存数据太大奔溃),然后循环把所有的对象都保存到db.

经过测试,上面的代码在执行过程中(persist 大于50条记录以后),并没有立即刷到db里面去,直到所有的都persist完成之后,数据库才看到记录。下面介绍从别的博客看到关于flush,和@Transtaction注解commit操作的区别,解释这种情况的原因;

flush和commit的区别

1、flush()方法进行清理缓存的操作,执行一系列的SQL语句,但不会提交事务;

     commit()方法会先调用flush()方法,然后提交事务. 提交事务意味着对数据库所做的更新会永久保持下来   所谓清理,是指Hibernate 按照持久化象的状态来同步更新数据库 。

2、Flush()后只是将Hibernate缓存中的数据提交到数据库,如果这时数据库处在一个事物当中,则数据库将这些SQL语句缓存起来

           当Hibernate进行commit时,会告诉数据库,你可以真正提交了,这时数据才会永久保存下来,也就是被持久化了.
3、commit针对事物的,flush针对缓存的, 数据同步到数据库中后只要没有commit还是可以rollback的。
       可以这么理解,hibiernate有二级缓存,而平时一般只用一级缓存(默认开启),也就是session级的缓存。处于一个事务当中。

         当save的时候,只是把相应的insert行为登记在了以及缓存上,而flush是把缓存清空,同时把insert行为登记在数据库的事务上。
         当commit提交之后,才会执行相应的insert代码,而commit又是隐性的调用flush的。

springboot jpa 批量保存数据--EntityManager和 JpaRepository的更多相关文章

  1. Jquery Easy UI Datagrid 上下移动批量保存数据

    DataGrid with 上下移动批量保存数据 通过前端变量保存修改数据集合,一次性提交后台执行 本想结合easyui 自带的$('#dg').datagrid('getChanges'); 方法来 ...

  2. 使用EntityManager批量保存数据

    @PersistenceContext EntityManager em; 从别的系统中定期同步某张表的数据,由于数据量较大,采用批量保存 JPA EntityManager的四个主要方法 ① pub ...

  3. 使用JDBC批量保存数据(JdbcDaoSupport,JdbcTemplete)

    最近做的一个项目中用到了Hibernate的,然后数据库批量插入数据的时候就使用到了hibernate的批处理,但是效率比较低,看网上说还有一些限制,要禁止二级缓存,还要多一个batch_size的配 ...

  4. Hibernate 批量保存数据

    public Boolean save(Collection<Object> os) { int batchSize = 50,i=0; Session session=this.sess ...

  5. (8). 使用JPA保存数据【从零开始学Spring Boot】

    在看这一篇文档的话,需要先配置好JPA – Hibernate. 总体步骤: (1)   创建实体类Demo,如果已经存在,可以忽略. (2)   创建jpa repository类操作持久化. (3 ...

  6. SpringBoot(18)---通过Lua脚本批量插入数据到Redis布隆过滤器

    通过Lua脚本批量插入数据到布隆过滤器 有关布隆过滤器的原理之前写过一篇博客: 算法(3)---布隆过滤器原理 在实际开发过程中经常会做的一步操作,就是判断当前的key是否存在. 那这篇博客主要分为三 ...

  7. Springboot+JPA下实现简易爬虫:豆瓣电视剧数据

    Springboot+JPA下实现简易爬虫:豆瓣电视剧数据 前言:今天听到产品那边讨论一些需求,好像其中一点是用户要求我们爬虫,在网页上抓取一些数据然后存到我们公司数据库中,众所周知,爬虫的实现对于p ...

  8. 8.使用JPA保存数据【从零开始学Spring Boot】

    转载:http://blog.csdn.net/linxingliang/article/details/51636989 在看这一篇文档的话,需要先配置好JPA – hibernate. 总体步骤: ...

  9. snapde的批量文件数据过滤保存功能

    一.snapde基本介绍 Snapde,一个专门为编辑超大型数据量CSV文件而设计的单机版电子表格软件:它运行的速度非常快,反应非常灵敏. 二.snapde批量数据筛选功能 如果想要对很多文件筛选出来 ...

随机推荐

  1. oracle 分区表详解

    一.分区表的概述: Oracle的表分区功能通过改善可管理性.性能和可用性,从而为各式应用程序带来了极大的好处.通常,分区可以使某些查询以及维护操作的性能大大提高.此外,分区还可以极大简化常见的管理任 ...

  2. CSS3 简介

    CSS3 简介 对CSS3已完全向后兼容,所以你就不必改变现有的设计.浏览器将永远支持CSS2. CSS3被拆分为"模块".旧规范已拆分成小块,还增加了新的. 一些最重要CSS3模 ...

  3. 20145216史婧瑶《Java 程序设计》第4周学习总结

    20145216 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承与多态 6.1 何谓继承 继承基本上就是避免多个类间重复定义共同行为. 在Java中,继承时使用exte ...

  4. 快用Visual Studio(五)- 语言特性

    HTML 自带Emment $ SHIFT + OPTION + F:格式化代码 其他语言特性提示 CSS & LESS hover属性,提示样式对象标签 $ CMD + SHIFT + O: ...

  5. nginx配置Strict Transport Security

    一个网站接受一个HTTP的请求,然后跳转到HTTPS,用户可能在开始跳转前,通过没有加密的方式和服务器对话,比如,用户输入http://zt.test.com或者直接zt.test.com.这样存在中 ...

  6. ubuntu16.04下安装mysql详细步骤

    1.如果要搭建服务器先去购买一个云主机,比如阿里云.京东云.新网等等都有卖.这里推荐使用京东云服务器,因为最近在搞活动.一元可体验两个月(可能现在活动已经过了,但在京东云里有免费领一个月的,学生机也有 ...

  7. java直接计算一个算术题

    import javax.script.ScriptEngine;import javax.script.ScriptEngineManager;import javax.script.ScriptE ...

  8. 配置了java环境变量后不起作用

    我的电脑上装了好几个版本的jdk,有jdk1.6.jdk1.8.但是我的环境变量是设置jdk1.6的.然而打开cmd,查看Java版本却显示的是1.8,这让我百思不得其解.后来发现了问题. 问题:在p ...

  9. java HTTP代码示例

    //测试环境发送用例 @Test public void testSendForTest() {     String url = "http://172.16.30.108:8138/ap ...

  10. 第八章:部署Tornado

    到目前为止,为了简单起见,在我们的例子中都是使用单一的Tornado进程运行的.这使得测试应用和快速变更非常简单,但是这不是一个合适的部署策略.部署一个应用到生产环境面临着新的挑战,既包括最优化性能, ...