Java Criteria API使用NOT in语句读取数据块中的数据
我正在使用Java Criteria API使用NOT in语句读取数据块中的数据,java,sql,db2,eclipselink,criteria-api,Java,Sql,Db2,Eclipselink,Criteria Api,我正在使用EclipseLink 2.6.4、Java8和DB2作为数据库。我必须编写查询来读取不在语句中的数据,该语句为不在语句提供大量值 基本上,我有一组超过10000个值的外部ID: Set<Integer> externalIDs = new HashSet<>(Arrays.asList("ExternalID1", "ExternalID2", "ExternalID3",....)); //externalIDs.size() == 10k+ 私有方法pa
EclipseLink 2.6.4
、Java8
和DB2
作为数据库。我必须编写查询来读取不在
语句中的数据,该语句为不在
语句提供大量值
基本上,我有一组超过10000个值的外部ID:
Set<Integer> externalIDs = new HashSet<>(Arrays.asList("ExternalID1", "ExternalID2", "ExternalID3",....)); //externalIDs.size() == 10k+
私有方法partionedNotIn()
只是将NOT IN
语句拆分为999个值的块,以使最大值不超过1000个
但正如您所看到的,我在语句中没有5个,每提供10000个值,总共是50000个,我达到了托管可变长度的DB限制
无论如何,我们的目标是将其分块,这样我就不会在语句中总共有50k+的值,目前也不知道如何实现这一点。只要在
语句中使用,就很容易了
任何建议都会有帮助。谢谢。您从哪里获得不在的值?如果它是一个文件,那么您可能可以使用外部表。或者创建一个临时表,将值插入该表并在查询中使用。将值存储在临时表中并根据它进行计算?!
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();
}