И / ИЛИ группировка ГДЕ условий с критериями-предикатами в Hibernate - PullRequest
0 голосов
/ 12 июня 2018

У меня проблема с группировкой условий WHERE.В конечном счете, моя цель - создать группы условий AND, каждое из которых является OR.Например:

SELECT *
WHERE ( foo = 1 AND bar = 2) 
OR (foo = 3 AND bar = 4)
OR (foo = 5 AND bar = 6)

Ниже приведен код, который я использую для этого.Как видите, я создаю 2 «равных» предиката, а затем создаю предикат, который их вкладывает.

List<Waybill> getWaybillsByCriteriaOrderItemList(List< OrderItem > orderItems ) {
    CriteriaBuilder cb = em.getCriteriaBuilder()
    CriteriaQuery<Waybill> q = cb.createQuery( Waybill )
    Root<Waybill> waybillRoot = q.from(Waybill)
    q.select( waybillRoot )
    List<Predicate> predicates = []


    orderItems.each { OrderItem item ->
        Predicate carInit = cb.equal( cb.trim(waybillRoot.get('carInit')), item.carInit)
        Predicate carNumb = cb.equal( cb.trim(waybillRoot.get('carNumb')), item.carNum )
        Predicate thisCar = cb.or (
                cb.and( carInit ),
                cb.and( carNumb )
        )
        predicates << thisCar
    }
    q.where(predicates.toArray(new Predicate[predicates.size()]))
    TypedQuery<Waybill> tq = em.createQuery(q)
    List<Waybill> result = tq.getResultList()
    result
}

К сожалению, группировка AND / OR в точности противоположна тому, что я ожидал.Вот сгенерированный HQL

select generatedAlias0 from Waybill as generatedAlias0 where 
( ( trim(BOTH   from generatedAlias0.carInit)=:param0 ) or ( trim(BOTH   from generatedAlias0.carNumb)=:param1 ) ) 
and 
( ( trim(BOTH   from generatedAlias0.carInit)=:param2 ) or ( trim(BOTH   from generatedAlias0.carNumb)=:param3 ) ) 
and
( ( trim(BOTH   from generatedAlias0.carInit)=:param4 ) or ( trim(BOTH   from generatedAlias0.carNumb)=:param5 ) ) 

Простое обращение этих методов и () и или () также не решило мою проблему.Это привело к тому, что все было так:

 Predicate thisCar = cb.and (
     cb.or( carInit ),
     cb.or( carNumb )
 )

~~~~

select generatedAlias0 from Waybill as generatedAlias0 where 
( ( trim(BOTH   from generatedAlias0.carInit)=:param0 ) and ( trim(BOTH   from generatedAlias0.carNumb)=:param1 ) )
and
( ( trim(BOTH   from generatedAlias0.carInit)=:param2 ) and ( trim(BOTH   from generatedAlias0.carNumb)=:param3 ) )
and
( ( trim(BOTH   from generatedAlias0.carInit)=:param4 ) and ( trim(BOTH   from generatedAlias0.carNumb)=:param5 ) )

Я перепробовал каждую комбинацию, о которой только мог подумать.Кто-нибудь может указать, что я делаю не так?

1 Ответ

0 голосов
/ 12 июня 2018

Попробуйте изменить:

Predicate thisCar = cb.or (
            cb.and( carInit ),
            cb.and( carNumb )
    );

на:

Predicate thisCar = cb.and( carInit , carNumb );

И после цикла добавьте оператор or в массив предикатов:

q.where(cb.or(predicates.toArray(new Predicate[] {})));
...