Как вы объединяете критерии «ИЛИ» при использовании запроса критериев с гибернацией?

79

Я пытаюсь выполнить простое «ИЛИ» для трех полей, используя запрос критериев гибернации.

пример

class Whatever{
 string name;
 string address;
 string phoneNumber;
}

Я хотел бы создать критерий запроса, в котором моя строка поиска могла бы соответствовать «имени», «адресу» или «номеру телефона».

ScArcher2
источник

Ответы:

133

Вы хотите использовать Restrictions.disjuntion(). Вот так

session.createCriteria(Whatever.class)
    .add(Restrictions.disjunction()
        .add(Restrictions.eq("name", queryString))
        .add(Restrictions.eq("address", queryString))
        .add(Restrictions.eq("phoneNumber", queryString))
    );

См. Документ Hibernate здесь .

бледный
источник
Это прекрасно, спасибо! Я наконец нашел пример в Интернете, но я рад, что он здесь для использования в будущем.
ScArcher2,
8
а если бы я захотел (name = x AND address = y) OR (phoneNumber = z)?
Кевин Мередит
71

Предполагая, что у вас есть под рукой сеанс гибернации, должно работать что-то вроде следующего:

Criteria c = session.createCriteria(Whatever.class);
Disjunction or = Restrictions.disjunction();
or.add(Restrictions.eq("name",searchString));
or.add(Restrictions.eq("address",searchString));
or.add(Restrictions.eq("phoneNumber",searchString));
c.add(or);
Роб Оксспринг
источник
4
Мне нравится синтаксис создания дизъюнкции и присвоения ей имени или. Это намного более читабельно, чем другое решение.
ScArcher2
Это было здорово :) Также согласен с @ ScArcher2, он очень удобен для чтения и значительно упростил понимание более сложного примера, который мне пришлось сделать.
Дастин Дженсен
12
    //Expression :  (c1 AND c2) OR (c3)      


     Criteria criteria = session.createCriteria(Employee.class);

      Criterion c1 = Restrictions.like("name", "%e%");
      Criterion c2 = Restrictions.ge("salary", 10000.00);
      Criterion c3 = Restrictions.like("name", "%YYY%");
      Criterion c4 = Restrictions.or(Restrictions.and(c1, c2), c3);
      criteria.add(c4);

// То же самое можно сделать для (c1 OR c2) AND c3 или любого сложного выражения.

Дхармендер Рават
источник
6
//Expression :  (c1 AND c2) OR (c3)      


 Criteria criteria = session.createCriteria(Employee.class);

  Criterion c1 = Restrictions.like("name", "%e%");
  Criterion c2 = Restrictions.ge("salary", 10000.00);
  Criterion c3 = Restrictions.like("name", "%YYY%");
  Criterion c4 = Restrictions.or(Restrictions.and(c1, c2), c3);
  criteria.add(c4);

  //Same thing can be done for (c1 OR c2) AND c3, or any complex expression.
Дхармендер Рават
источник
3

На всякий случай кто-нибудь наткнется на это с тем же вопросом для NHibernate:

ICriteria c = session.CreateCriteria(typeof (Whatever))
    .Add(Expression.Disjunction()
        .Add(Expression.Eq("name", searchString))
        .Add(Expression.Eq("address", searchString))
        .Add(Expression.Eq("phoneNumber", searchString)));
Гейр-Тор Линдсве
источник
1

Условия могут применяться с помощью или / и на разных уровнях запроса с помощью дизъюнкции.

Criteria query = getCriteria("ENTITY_NAME");
query.add(Restrictions.ne("column Name", current _value));

Disjunction disjunction = Restrictions.disjunction();

if (param_1 != null)
    disjunction.add(Restrictions.or(Restrictions.eq("column Name", param1)));

if (param_2 != null)
    disjunction.add(Restrictions.or(Restrictions.eq("column Name", param_2)));

if (param_3 != null)
    disjunction.add(Restrictions.or(Restrictions.eq("column Name", param_3)));
if (param_4 != null && param_5 != null)
    disjunction.add(Restrictions.or(Restrictions.and(Restrictions.eq("column Name", param_4 ), Restrictions.eq("column Name", param_5 ))));

if (disjunction.conditions() != null && disjunction.conditions().iterator().hasNext())
    query.add(Restrictions.and(disjunction));

return query.list();
Тьяго Медичи
источник
возможно ли получить null для всех элементов, не найденных в базе данных?
fiddle
Это согласованно: возвращается список со всеми результатами, независимо от того, есть они или нет.
Тьяго Медичи
1

Это то, что сработало для меня с условием ИЛИ, которое тоже с условием IN, а не с ответом, получившим наибольшее количество голосов в этом обсуждении:

criteria.add( Restrictions.or(
                    Restrictions.eq(ch.getPath(ch.propertyResolver().getXXXX()), "OR_STRING"),
                        Restrictions.in(ch.getPath(ch.propertyResolver().getYYYY()), new String[]{"AA","BB","CC"})
                    ));

Результирующий запрос:

  and (
            this_.XXXX=? 
            or this_.YYYY in (
                ?, ?, ?
            )
        ) 
ронак
источник
1

Если кто-то использует CriteriaQuery вместо Criteria, вы можете поместить все свои выражения в Predicateсписок и поставить OR по размеру предикатов следующим образом:

List<Predicate> predicates = new ArrayList<>();
if (...) {
  predicates.add(...);
}

criteriaQuery.where(cb.or(predicates.toArray(new Predicate[predicates.size()])));
Гаспар
источник