我正在使用 EclipseLink 2.6.4
、Java 8
和 DB2
作为数据库。我必须编写查询以使用 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/