java - Criteria API 使用 NOT IN 语句分块读取数据

标签 java sql db2 eclipselink criteria-api

我正在使用 EclipseLink 2.6.4Java 8DB2 作为数据库。我必须编写查询以使用 NOT IN 语句读取数据,为 NOT IN 语句提供大量值。

基本上我有一组具有超过 10000 个值的外部 ID:

Set<Integer> externalIDs = new HashSet<>(Arrays.asList("ExternalID1", "ExternalID2", "ExternalID3",....)); //externalIDs.size() == 10k+

注意:我知道 DB2 的 NOT IN 语句的限制是 1000 个值,所以我在查询中创建分区的 NOT IN 语句,它看起来像这个:

public List<UserEntity> findNotReferencedToRemove2(Set<String> externalIds) {

  CriteriaBuilder cb = entityManager.getCriteriaBuilder();
  CriteriaQuery<UserEntity> cq = cb.createQuery(UserEntity.class);
  Root<UserEntity> root = cq.from(UserEntity.class);

  Path<String> externalId1 = root.get(UserEntity_.relation1).get(RelationEntity1_.externalId);
  Path<String> externalId2 = root.get(UserEntity_.relation2).get(RelationEntity2_.externalId);
  Path<String> externalId3 = root.get(UserEntity_.relation3).get(RelationEntity3_.externalId);
  Path<String> externalId4 = root.get(UserEntity_.relation4).get(RelationEntity4_.externalId);
  Path<String> externalId5 = root.get(UserEntity_.relation5).get(RelationEntity5_.externalId);

  Predicate predicate = cb.and(
      partitionedNotIn(cb, externalId1, externalIds),
      partitionedNotIn(cb, externalId2, externalIds),
      partitionedNotIn(cb, externalId3, externalIds),
      partitionedNotIn(cb, externalId4, externalIds),
      partitionedNotIn(cb, externalId5, externalIds)
  );

  return entityManager.createQuery(cq.where(predicate)).getResultList();
}

//creates NOT IN statement splited in chunks of 999 values connected with AND 
private<C> Predicate partitionedNotIn(CriteriaBuilder cb, Path<C> path, Collection<C> ids) {
    if (ids.isEmpty()) {
      return cb.and();
    }
    return cb.and(partition(ids).stream().map(path::in).map(cb::not).toArray(Predicate[]::new));
  }

  private <C> Collection<List<C>> partition(Collection<C> list) {
    final AtomicInteger counter = new AtomicInteger(0);
    return list.stream()
        .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / 999))
        .values();
  }

私有(private)方法 partionedNotIn() 只是将 NOT IN 语句拆分为 999 个值的 block ,以免达到 1000 个值的最大值。

但如您所见,我有 5 个 NOT IN 语句,每提供 10000 个值,总数为 50000,我在托管变量长度的数据库中达到了限制。

无论如何,我们的目标是将其拆分成多个 block ,因此我没有 50k+ 的值用于 NOT IN 语句,目前不知道如何实现这一点。只需 IN 语句就很容易了。

任何建议都会有所帮助。谢谢。

最佳答案

您从哪里获得 not in 的值?它是一个文件,那么你也许可以使用外部表。或者创建一个临时表并将值插入该表并在您的查询中使用它。

关于java - Criteria API 使用 NOT IN 语句分块读取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58495780/

相关文章:

java - Spring是否允许在非抽象中转换抽象bean?

php - sql中如何划分学生

sql - SQL临时表上的红色错误行

sql - 在 vba 中使用 ADODB 在 SQL 中命名变量

java - Hibernate DB2 在使用 NativeQuery 时返回第一个字符 vector

java - NoSuchElementException 错误

Java调用方法返回值作为switch case值

java - 以 DB2 作为后端的 jsp 分页

c# - 进程类 db2cmd c#

java - 获取单词的第一个字母并将其放在最后