Критерии API комбинированные И / ИЛИ - PullRequest
3 голосов
/ 27 августа 2011

Я изо всех сил пытаюсь создать запрос, используя Criteria API.Следующий SQL-запрос возвращает результат, который мне нужен:

SELECT * FROM MODEL WHERE MANUFACTURER_ID = 1 AND SHORTNAME LIKE '%SF%' OR LONGNAME LIKE '%SF%';

Я написал следующий код с использованием API критериев:

public List<Model> findAllByManufacturer(Manufacturer manufacturer,
        String pattern) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Model> cq = cb.createQuery(Model.class);
    Root<Model> m = cq.from(Model.class);
    cq.select(m);
    Join<Model, Manufacturer> mf = m.join("manufacturer");
    Predicate p = cb.equal(mf.get("id"), manufacturer.getId());
    p = cb.and(cb.like(cb.upper(m.<String>get("shortName")),
            pattern.toUpperCase()));
    p = cb.or(cb.equal(cb.upper(m.<String>get("longName")),
            pattern.toUpperCase()));
    cq.where(p);
    return em.createQuery(cq).getResultList();
}

Когда я думаю об этом логически, он должен работать:

Predicate p = cb.equal(mf.get("id"), manufacturer.getId());

WHERE MANUFACTURER_ID = 1

p = cb.and(cb.like(cb.upper(m.<String>get("shortName")),
                pattern.toUpperCase()));

И ИМЯ SHORTNAME '% SF%'

p = cb.or(cb.equal(cb.upper(m.<String>get("longName")),
                pattern.toUpperCase()));

ИЛИ LONGNAME LIKE '% SF%'

Запрос выполняется правильно, я не получаю никаких ошибок, он просто не возвращает никаких результатов.Любая подсказка, где я ошибся, очень ценится!

1 Ответ

6 голосов
/ 27 августа 2011

Вы проверили сгенерированный SQL?

Вы создаете предикат и присваиваете ему p, но затем вы создаете другой и присваиваете его той же переменной p.

Я думаю, что это должно быть:

Predicate predicateOnManufacturerId = cb.equal(mf.get("id"), 
                                               manufacturer.getId());
Predicate predicateOnShortName = cb.like(cb.upper(m.<String>get("shortName")),
                                         pattern.toUpperCase()));
Predicate predicateOnLongName = cb.equal(cb.upper(m.<String>get("longName")),
                                         pattern.toUpperCase()));
Predicate p = cb.or(cb.and(predicateOnManufacturerId, 
                           predicateOnShortName),
                    predicateOnLongName);
cq.where(p);

Кроме того, почему бы вам не использовать метамодель ваших сущностей:

Join<Model, Manufacturer> mf = m.join(Model_.manufacturer);
... cb.equal(mf.get(Manufacturer_.id);
...

Это было бы более безопасно для типов, и вы могли бы обнаружить неправильные запросы во время компиляции, а не во время выполнения.

...