Создание спецификации в цикле

97
24 апреля 2021, 02:20

Всем привет, такой вопрос. Есть список который может содержать более 1000 элементов, по которому надо сделать сравнение. Oracle не позволяет добавить в один 'in' более 1000 элементов, по этому хочу через цикл разбить один большой запрос на несколько поменьше. Для этого использую следующий метод (в коде ограничено числом 3 чтобы локально воспроизвести, в h2 лежит меньше сущностей):

    public Page<DivisionView> getDivisions(Pageable pageable, String q, Long macroRegionId) {
    User loggedUser = userRepository.findOne(idEquals(SecurityContextUtils.getLoggedUserId()));
    Set<Long> shopIds = shopRepository.findAll(shopService.specificationByRole(loggedUser)).stream().map(Shop::getId).collect(Collectors.toSet());
    Specification<OrgStructureDivision> specification = null;
    Specification<OrgStructureDivision> shopSpecification = null;
    Set<Long> thousandIds = new HashSet<>();
    for (Long id: shopIds) {
        if (thousandIds.size() < 3) {
            thousandIds.add(id);
        } else {
            shopSpecification = divisionSpecificationForThousandIds(shopSpecification, thousandIds);
            thousandIds.clear();
        }
    }
    shopSpecification = divisionSpecificationForThousandIds(shopSpecification, thousandIds);
    specification = where(specification).and(shopSpecification);
    return repository.findAll(specification, pageable).map(DivisionView::buildFromEntity);
}

private Specification<OrgStructureDivision> divisionSpecificationForThousandIds(Specification<OrgStructureDivision> shopSpecification, Set<Long> thousandIds) {
    return shopSpecification == null
            ? shopIn(thousandIds)
            : where(shopSpecification).or(shopIn(thousandIds));
}

Есть спецификация:

    public static Specification<OrgStructureDivision> shopIn(Set<Long> shopIds) {
    return (root, criteriaQuery, cb) -> {
        criteriaQuery.distinct(true);
        Join<OrgStructureCluster, Shop> shopJoin = root.join(OrgStructureDivision_.clusters).join(OrgStructureCluster_.shops);
        return shopJoin.in(shopIds);
    };
}

на выходе получается что то вроде:

select distinct orgstructu0_.division_id     as division1_41_,
            orgstructu0_.external_id     as external2_41_,
            orgstructu0_.external_system as external3_41_,
            orgstructu0_.active          as active4_41_,
            orgstructu0_.guid            as guid5_41_,
            orgstructu0_.macro_region_id as macro_re7_41_,
            orgstructu0_.name            as name6_41_
from structure_division orgstructu0_
         inner join structure_cluster clusters1_ on orgstructu0_.division_id = clusters1_.division_id
         inner join shop shops2_ on clusters1_.id = shops2_.cluster_id
         inner join structure_cluster clusters3_ on orgstructu0_.division_id = clusters3_.division_id
         inner join shop shops4_ on clusters3_.id = shops4_.cluster_id
where (shops4_.id in (5) or shops2_.id in (5));

Проблема в том что в списке приходит (-2, 1, 2, 4, 5) а в спецификации всё обрубается и несколько раз по in (5) проверяет. Подскажите пожалуйста с чем это может быть связано?

Answer 1

Я не уверен но в вашем варианте два раза вызов есть в цикле и потом без цикла

divisionSpecificationForThousandIds

Как вариант сделать временную таблицу и запихнуть туда все id. А потом сделать

your_sql WHERE some_id IN ( SELECT some_id FROM some_tmp_table )

READ ALSO
Одна Entity и Две @OneToOne анотации

Одна Entity и Две @OneToOne анотации

В таблице Location содержится информация которая должна выбираться согласно связи charactersorigin_id reference to location

109
Как докачать расширения в Android Studio?

Как докачать расширения в Android Studio?

При первом запуске Android Studio возникает окно, с помощью которого можно установить все необходимые расширения, но после создания первого проекта,...

94
Кластеризация в Mapbox с использованием SymbolManager

Кластеризация в Mapbox с использованием SymbolManager

Пытаюсь сделать кластеризацию в приложении с использованием библиотеки mapbox и их плагина аннотацийВ разрабатываемом приложении необходимо...

104
Метод JPArepository.save() кидает NullpointerException

Метод JPArepository.save() кидает NullpointerException

Пожалуйста помогите решить эту проблему, хотя бы в какую сторону копать решение

85