【问题标题】:CrudRepository and Hibernate: save(List<S>) vs save(Entity) in transaction [closed]CrudRepository 和 Hibernate:事务中的保存(List<S>)与保存(实体)[关闭]
【发布时间】:2015-12-23 22:46:03
【问题描述】:

如果我这样做会有什么不同吗:

@Transactional
public void processData() {
    List<MyEntity> entities = ....;
    MyEntityRepository.save(entities);
}

对比

@Transactional
public void processData() {
    List<MyEntity> entities = ....;
    for (MyEntity entity : entities) {
        MyEntityRepository.save(entity);
    }
}

在底层查询和性能方面有什么区别?

【问题讨论】:

    标签: java spring hibernate jpa


    【解决方案1】:

    来自SimpleJpaRepository

    @Transactional
    public <S extends T> List<S> More save(Iterable<S> entities) {
    
        List<S> result = new ArrayList<S>();
    
        if (entities == null) {
            return result;
        }
    
        for (S entity : entities) {
            result.add(save(entity));
        }
    
        return result;
    }
    

    因此,您的第二个业务方法仅影响 save(Iterable&lt;S&gt; entities) Crud Repository 方法,因为它迭代列表并代表您调用 save(S)

    只要事务与您的processData 业务方法分界,性能或执行的查询就没有真正的差异。

    【讨论】:

    • 如果我的列表包含多个具有相同主键的实体,然后我调用save(List&lt;S&gt; entities),它会给出约束异常。但是,如果我迭代(即第二种业务方法),它不会抱怨。这是为什么呢?
    • 有趣。我的猜测是@Transactional 不知何故不适用于processData(),所以在第二个变体中,每个迭代都在它自己的事务上下文中运行,因此成功。
    • @AshishLohia 保存方法可用于单个对象或对象列表作为参数。人们可能会认为它会有所帮助,因为它是“批量插入”,但正如您在上面看到的那样,情况并非如此。
    【解决方案2】:

    正如Ori Dar 所提到的,没有真正的区别。

    但是,有一点你应该注意:根据2.2.0.M1中的repo history,用于保存元素列表的方法已重命名为&lt;S extends T&gt; List&lt;S&gt; saveAll(Iterable&lt;S&gt; entities),而save方法不再需要作为参数列表。

    由于我没有 50 声望来评论上面的答案或问题,我必须写一个关于此更改的新答案。

    【讨论】:

      【解决方案3】:

      对于 SpringData Jpa,更简洁的方法是使用 repository.saveAll 而不是 forloop 和 repository.savesaveAll 会自动遍历列表并保存。

      saveAll 是 JpaRepository 的一部分,所以不需要定义任何方法。

      【讨论】:

        【解决方案4】:

        saveAll 可能快 5 到 20 倍,因为当 .save() 每次执行时都会打开一个新事务,它伴随着 1 个事务。 使用一个且唯一的事务使其更快,并且不会更多地使用内存

        证明: Spring data save vs saveAll performance https://www.baeldung.com/spring-data-save-saveall

        【讨论】:

        • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 1970-01-01
        • 2019-04-05
        • 1970-01-01
        • 2010-10-05
        • 1970-01-01
        • 2018-05-27
        • 1970-01-01
        • 2014-07-14
        • 1970-01-01
        相关资源
        最近更新 更多