【问题标题】:Avoid Spring Data JPA Selections before Saving an Entity在保存实体之前避免 Spring Data JPA 选择
【发布时间】:2019-11-03 01:08:52
【问题描述】:

这是场景,我正在使用 Spring Data JPA JpaRepository 保存一个实体(我们称之为 CG 实体)。在这个 CG 实体中,我们有很多实体 One-One、One-Many 和 M-M,在这些实体内部,还有更多的关系等等。我通过其主键设置 CG 实体并向其添加其他实体对象。所以基本上这个 CG 实体 PK 应该用作 CG 中大多数其他实体的 FK。

一些实体是新的,而另一些实体是通过创建具有给定主 ID 的对象来设置的(因此无需使用相关的存储库来查找和设置对象)。在模型类中,所有的初选都是手动设置的(没有自动生成策略)(我不能公开表结构,因为我不允许这样做) 当我调用 .save() 函数时,JPA 运行此函数

    @Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

从这里 Spring JPA 通过创建选择查询来检查 CG 是否是新实体。当我使用调试器中显示的 SQL 查询时,我观察到它使用了近 70 个 SELECT 查询。 在 spring 文档Persistable 中,我实现了它并将覆盖isNew() 设置为false。我对那些由 PK 创建的对象做了同样的事情。

但是当我为整个操作调用.save()时,spring data JPA在插入前运行了近800个SELECT查询,并且有70个INSERT查询(插入查询没有问题)。保存条目大约需要 20 秒。我提到了很多与此场景相关的线程,但无法找到一个好的 SPRING DATA JPA 解决方案。 (所以Thread 1) 我所需要的只是减少保存 CG 实体的时间。有没有 Spring Data JPA 方法来实现这一点?

【问题讨论】:

  • 这不是 Spring Data JPA,而只是 JPA“问题”。这就是 JPA 的工作方式,与调用保存/合并无关。对于现有实体,它将进行脏检查以查看是否需要更新内容,它还将尝试在这些实体(选择)中加载引用。您想要的是优化批处理的此过程并将刷新模式设置为手动(而不是自动)并定期刷新和清除(按此顺序)第一级缓存(实体管理器)。
  • @M.Deinum 所以你的意思是我必须手动实现保存查询?你能分享一些关于你所说的教程吗?谢谢回复
  • 不,我不是。我是说您应该针对批处理进行优化,从而将刷新模式设置为手动并定期调用flushclear。我没有说你应该编写自己的查询。
  • @M.Deinum 啊谢谢你的推荐,我去看看批处理。
  • 您需要使用构建和保存实体的代码更新您的问题。

标签: java spring hibernate jpa spring-data-jpa


【解决方案1】:

好的,通过以下操作解决了这个问题;

  1. 设置FetchType

    需要将所有FetchType 设置为FetchType.LAZY。在我的模型中,其中一些丢失了。没有添加任何 Fetchtypes。所以对于所有@OneToMany 关系,这是介绍

  2. 启用事务

    以前在 Spring Web 应用程序中,事务未启用。使用@EnableTransactionManagement启用,相关服务方法注解为@Transactional

通过上述操作,我能够最大限度地减少保存条目所花费的时间。现在有近 200-300 个查询在 2-4 秒内运行。

PS:总是为惰性设置 FetchTypes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    相关资源
    最近更新 更多