JPA的saveAndFlush

#Stable Diffusion 美图活动一期#

关于MyBatis与JPA:

笔者初次接触这两个持久层框架的时候,那还是得从iBatis、Hibernate开始说起。那时候知道的一个很浅显、但最明显的区别就是:iBatis是半自动化的ORM框架,适用于表关联关系复杂的项目;Hibernate是全自动化的ORM框架,适用于表关联关系简单的项目。

个人还是比较喜欢用MyBatis的,那种你可以随意掌控SQL的自由是无法溢于言表的,虽然要时刻提心吊胆的考虑数据库兼容性。

业务背景:

最近在处理一个从第三方接口获取数据并持久化的业务,当数据量达到3000条左右的时候,整个过程耗时将近130s,离大谱。

问题分析及定位:

一开始本着专业甩锅的精神,怀疑是第三方接口比较拉跨,我们也确实有不具任何说明力的证据,即数据量小的时候,接口调用耗时占了大头。

但甩锅归甩锅,自查还是要进行的。数据量级过百之后,耗时大头就不再是接口调用了,经过多次调试最终定位了问题所在行:saveAndFlush。

抢救手段:

1、将一些基础查询的结果缓存在内存中;

2、根据业务字段对接口结果集进行去重;

3、调整代码结构,将saveAndFlush改为saveAllAndFlush;

4、配置批量操作参数;

spring:
  jpa:
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQL9Dialect
        hbm2ddl:
          auto: none
        format_sql: true
        jdbc:
          batch_size: 1000
          fetch_size: 1000
          batch_versioned_data: true
        order_inserts: true
        order_update: true

结果:

收效甚微,耗时没有任何质的提升。

好奇:

这个批量操作到底做甚了???

    @Transactional
    public <S extends T> List<S> saveAll(Iterable<S> entities) {
        Assert.notNull(entities, "Entities must not be null!");
        List<S> result = new ArrayList();
        Iterator var3 = entities.iterator();

        while(var3.hasNext()) {
            S entity = var3.next();
            result.add(this.save(entity));
        }

        return result;
    }

继续好奇:

那这个 saveAndFlush又干的啥?

    @Transactional
    public <S extends T> S saveAndFlush(S entity) {
        S result = this.save(entity);
        this.flush();
        return result;
    }

GO ON

    @Transactional
    public <S extends T> S save(S entity) {
        Assert.notNull(entity, "Entity must not be null.");
        if (this.entityInformation.isNew(entity)) {
            this.em.persist(entity);
            return entity;
        } else {
            return this.em.merge(entity);
        }
    }

但凡用过hibernate或jpa的看到这都能明白,而且这个保存或更新本身也是“全自动”框架提供的一个特点。

结论:

既然目前使用JPA在框架层面没有特别好的解决办法,我们能不能人工干预一下呢?将接口返回的结果集,按业务进行人工分离,需要保存的一伙,需要更新的一伙,然后直接使用EntityManager的persist和merge。

实践验证:

使用EntityManager的persist和merge之后,总耗时控制在15s左右,效率提升了8-9倍,比较可观,3000条数据的时候,接口调用跟数据持久化耗时各占一半,这结果还是比较可以接受的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wsdhla

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值