zoukankan      html  css  js  c++  java
  • springboot jpa 批量保存数据--EntityManager和 JpaRepository

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

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

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

        @Transactional
        public <S extends T> List<S> save(Iterable<S> entities) {
            List<S> result = new ArrayList();
            if(entities == null) {
                return result;
            } else {
                Iterator var3 = entities.iterator();
    
                while(var3.hasNext()) {
                    S entity = var3.next();
                    result.add(this.save(entity));
                }
    
                return result;
            }
        }

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

        @Transactional
        public <S extends T> S save(S entity) {
            if(this.entityInformation.isNew(entity)) {
                this.em.persist(entity);
                return entity;
            } else {
                return this.em.merge(entity);
            }
        }

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

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

    public void persist(Object entity);

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

        public <T> T merge(T entity);

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

        public void refresh(Object entity);

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

        public void remove(Object entity);

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

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

    package com.sysware.cloud.dts.service;
    
    import com.sysware.cloud.dts.dtcs.entity.DistributedTransactionEntity;
    import com.sysware.cloud.dts.model.DistributedTransaction;
    import com.sysware.cloud.dts.redis.client.DtsRedisClient;
    import com.sysware.cloud.sys.util.BeanUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.annotation.Resource;
    import javax.persistence.EntityManager;
    import java.util.List;
    
    /**
     * Created by tianwenqing on 2018/7/4.
     */
    @Service
    @Transactional
    @Slf4j
    public class DistributeTransactionService {
    
        @Autowired
        private EntityManager entityManager;

    public void batchSave(List<DistributedTransaction> lst) { int j = 0; for (DistributedTransaction distributedTransaction : lst) { //TODO 判断数据的合法性 entityManager.persist(distributedTransaction); j++; if (j % 50 == 0 || j == lst.size()) { try { entityManager.flush(); }catch (Exception e){ log.error("fail",e); }finally { entityManager.clear(); } } } } }

    上面的逻辑是批量插入很多数据,然后自己模拟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的。
  • 相关阅读:
    Android画图最基本的三个对象(Color,Paint,Canvas)
    搭建Android开发环境之旅
    对象序列化与反序列化
    JUnit 3.8 演示递归删除文件目录的 测试类程序 .
    JUnit 3.8 让所有测试程序 实现 复合的测试(TestSuite)
    JUnit 3.8 通过反射测试私有方法
    Java NIO
    Java泛型 类型变量的限定
    组织领导层在信息化建设中须要解决的问题
    bootstrap之鼠标操作
  • 原文地址:https://www.cnblogs.com/wenq001/p/9264861.html
Copyright © 2011-2022 走看看