当前位置: 首页 > 知识库问答 >
问题:

Spring Boot-通过JPQL UPDATE查询批量更新数十万个对象?

养淇
2023-03-14

我正在使用具有HiberNate的Spring Boot1.5.2。

我有一个对象列表。每个对象都包含许多属性和@OneTo许多关系(即从数据库中获取此对象并将此对象更新到数据库需要很长时间)。

这就是我使用自定义 JPQL 查询的原因:

  • 一个用于加载对象列表的基本属性
  • 一个用于更新对象所需的属性
@Entity
@Table(name = coverage)
@Inheritance(strategy = InheritanceType.JOINED)
public class Coverage implements Serializable {
    @Id
    @JsonIgnore
    @Column(name = COLUMN_ID)
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected long id;

    @Column(name = "coverage_id", unique = true)
    protected String coverageId;

    ... many more properties
}

我从CrudRepository扩展了这个方法,用于获取对象列表(只有所需的属性)

@Transactional
public interface CoverageRepository extends CrudRepository<Coverage, String> {
    @Query("Select id, coverageId from Coverage")
    List<Object[]> readAllCoverageIdsAndTypes();

    @Modifying
    @Query("update Coverage set coverageId = :coverageId where id = :id")
    void saveCoverage(@Param("id") long id, @Param("coverageId") String coverageId);
}

现在,我想通过以下公式更新每个Coverage对象的coverageId:

newCoverageId = coverageId + randomString.

因此,我有一个覆盖范围对象列表,其中包含更新的coverageId。有10万个物体。

我做的事情非常缓慢:

    @Autowired
    CoverageRepository coverageRepository;
   
    @Transactional
    public void saveAllCoverages(List<Coverage> coverages) {
        for(Coverage coverage : coverages) {
           long id = coverage.getId();
           String newCoverageId = coverage.getCoverageId();
           this.coverageRepository.saveCoverage(id, newCoverageId);
        }
    }

性能很差,因为HiberNate每次迭代都会发送一个UPDATE查询。我如何让它更快?我想每个事务向postgreql发送100个查询,例如(批量更新)。

共有1个答案

楚墨一
2023-03-14

您可以使用ExecutorService。这里有完整的描述。

ExecutorService是一个JDK API,它简化了异步模式下的运行任务。一般来说,ExecutorService会自动提供一个线程池和一个为其分配任务的API。创建ExecutorService最简单的方法是使用Executors类的工厂方法之一。

例如,以下代码行将创建一个包含10个线程的线程池:

ExecutorService executorService = Executors.newFixedThreadPool(10); //init

executorService.execute(() -> YOUR_WORK_HERE);//usage
 类似资料:
  • 如何通过 TypeORM 中的原始查询进行批量更新? 例如,我们有具有属性名称的模型 User 如何在一个事务中更改几个用户的名称? 类型orm版本:0.2.7 数据库:后记

  • 问题内容: 有什么方法可以简化为一个查询吗? 问题答案: 是的,您可以使用以下查询进行操作:

  • 问题内容: 我正在使用 Elasticsearch 2.3 和 官方php驱动程序 。该 updateByQuery 是给我的烦恼在PHP中使用。对于如何使用它的一些帮助将不胜感激。 基本上我想更新几个与某个查询匹配的 文档 字段(名称,价格) 谢谢。 问题答案: 因此,借助CURL api的工作原理,我设法提出了一种方法。 首先,您需要编辑您的脚本以允许脚本。最后添加以下几行。 之后,您可以开始

  • 我想更新索引中的所有文档。我发现更新查询是我们应该使用的方法。但是,当我使用ctx._now作为更新文档字段的值时,我遇到了问题,导致字段值变为NULL。 这是示例: 当我使用随机数值时,它是工作。假设我把timenow=5。然后,All documents字段timenow变为5。但是,使用这种ctx方法是行不通的。 我该怎么做呢? 附加信息 示例:POST INDEX/TYPE/24/_UPD

  • 问题内容: 我当前正在使用Elasticsearch V2.3.1。我想在Java中使用以下Elasticsearch查询。 上面的查询搜索名为“ kimchy”的“用户”,并使用给定值更新“列表”字段。该查询同时更新多个文档。我在https://www.elastic.co/guide/en/elasticsearch/client/java- api/2.3/java-docs- update

  • 我有一个遗留代码,不允许使用预先准备好的语句。它使用Spring JDBC和更新查询。要求更新100000行。我有一张地图,上面有行号和需要在特定列中更新的值。 下面是我的当前代码: 我需要将其更改为批量执行,以便在for循环之后,我可以在一次DB命中中执行它。 对于这个需求,使用spring JDBC批处理更新的最佳方式是什么?