首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Spring数据Jpa实现批量更新?

如何使用Spring数据Jpa实现批量更新?
EN

Stack Overflow用户
提问于 2015-11-01 12:37:11
回答 5查看 42.8K关注 0票数 11

如何使用Spring数据Jpa实现批量更新?我有一个商品实体,对于不同的用户级别有不同的价格。

代码语言:javascript
复制
goodsId level price
  1       1     10
  1       2     9
  1       3     8

当更新商品时,我想批量更新这些价格,如下所示:

代码语言:javascript
复制
@Query(value = "update GoodsPrice set price = :price where goodsId=:goodsId and level=:level")
void batchUpdate(List<GoodsPrice> goodsPriceList);

但它会抛出异常,

代码语言:javascript
复制
Caused by: java.lang.IllegalArgumentException: Name for parameter binding must not be null or empty! For named parameters you need to use @Param for query method parameters on Java versions < 8.  

那么如何正确地使用Spring实现批更新呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-11-02 21:11:04

根据文档的说法,我认为Spring不可能做到这一点。您必须看看普通的JDBC,关于批处理插入/更新有几种方法

然而,你可以很容易地用Hibernate做这件事。.

票数 8
EN

Stack Overflow用户

发布于 2020-07-01 10:43:03

遵循这个示例:弹簧数据JPA批量插入,我创建了自己的方法来更新它,而不必处理EntityManager。

我这样做的方式是首先检索我想要更新的所有数据,在您的例子中,它将是WHERE goodsId=:goodsId AND level=:level。然后使用for循环循环遍历整个列表,并设置我想要的数据。

代码语言:javascript
复制
List<GoodsPrice> goodsPriceList = goodsRepository.findAllByGoodsIdAndLevel();
for(GoodsPrice goods : goodsPriceList) {
  goods.setPrice({{price}});
}
goodsRepository.saveAll(goodsPriceList);

以下部分是插入或更新所需的。拥有generate_statistics,这样您就可以看到是否真的在批处理它。

代码语言:javascript
复制
// for logging purpose, to make sure it is working
spring.jpa.properties.hibernate.generate_statistics=true
// Essentially key to turn it on
spring.jpa.properties.hibernate.jdbc.batch_size=4
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true

原木在这里

代码语言:javascript
复制
27315 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    603684 nanoseconds spent preparing 4 JDBC statements;
    3268688 nanoseconds spent executing 3 JDBC statements;
    4028317 nanoseconds spent executing 2 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    6392912 nanoseconds spent executing 1 flushes (flushing a total of 3 entities and 0 collections);
    0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
票数 5
EN

Stack Overflow用户

发布于 2017-08-16 14:03:02

如果您正在使用Hibernate,那么如果您愿意亲自管理事务,则可以选择。

下面是测试示例

代码语言:javascript
复制
int entityCount = 50;
int batchSize = 25;

EntityManager entityManager = null;
EntityTransaction transaction = null;

try {
    entityManager = entityManagerFactory().createEntityManager();

    transaction = entityManager.getTransaction();
    transaction.begin();

    for ( int i = 0; i < entityCount; ++i ) {
        if ( i > 0 && i % batchSize == 0 ) {
            entityManager.flush();
            entityManager.clear();

            transaction.commit();
            transaction.begin();
        }

        Post post = new Post(String.format( "Post %d", i + 1 ) );
        entityManager.persist( post );
    }

    transaction.commit();
} catch (RuntimeException e) {
    if ( transaction != null && transaction.isActive()) {
        transaction.rollback();
    }
    throw e;
} finally {
    if (entityManager != null) {
        entityManager.close();
    }
}

还建议将下列属性设置为适合您的需要的属性。

代码语言:javascript
复制
<property
    name="hibernate.jdbc.batch_size"
    value="25"
/>

<property
    name="hibernate.order_inserts"  
    value="true"
/>

<property
    name="hibernate.order_updates"  
    value="true"
/>

所有这些都摘自以下文章。使用JPA和Hibernate进行批处理的最佳方法

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33462221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档