【问题标题】:Spring boot - Batch Update for hundred thousands of objects by a JPQL UPDATE query?Spring boot - 通过 JPQL UPDATE 查询批量更新数十万个对象?
【发布时间】:2021-11-20 14:11:28
【问题描述】:

我正在使用带有 Hibernate 的 Spring Boot 1.5.2。

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

这就是我使用自定义 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 的 Coverage 对象列表。有 100 000 个对象。

我正在做的方式非常缓慢:

    @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 查询。我怎样才能让它更快? 我想向 postgresql 发送 100 个查询,例如(批量更新)每个事务。

【问题讨论】:

  • 您是否启用了批量更新?你的批量有多大。根据您的数据库,您可能需要一些额外的配置来启用批处理。
  • randomString 实际上是一个随机字符串吗?如果是这样,我会检查你的数据库是否有随机函数,并在不加载数据库的情况下进行完整的更新。
  • @JensSchauder randomSring 是从其他地方获取的,不可能从数据库中获取。所以,我不能使用数据库中的函数。

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


【解决方案1】:

您可以使用 ExecutorService。 Full description here.

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

例如,下面这行代码将创建一个有 10 个线程的线程池:

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

executorService.execute(() -> YOUR_WORK_HERE);//usage

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-02
    • 2020-07-03
    • 2021-08-13
    • 1970-01-01
    • 2011-07-07
    • 2015-02-07
    • 1970-01-01
    • 2014-10-21
    相关资源
    最近更新 更多