Hibernate Criteria Builder: Как отфильтровать по атрибуту объекта, который может быть обнуляем? - PullRequest
2 голосов
/ 24 сентября 2019

Сценарий

У меня есть объект Treatment, у которого есть два FK:

@ManyToOne
@JoinColumn(name = "product_id", nullable = true)
private Product product;

@ManyToOne
@JoinColumn(name = "product2_id", nullable = true)
private Product product2;

Этот объект Product имеет атрибут обычного идентификатора как PK.

Что я хочу:

Я хочу найти все процедуры, в которых любой из идентификаторов продуктов соответствует заданному, в нативном SQL это будет выглядеть примерно так:

select t.id, product_id,product2_id, p1.category_id,p2.category_id
from Treatment t
left join product p1 on t.product_id=p1.id
left join product p2 on t.product2_id=p2.id
where p1.category_id=17 or p2.category_id=17

То, что я имеюсделано до сих пор:

Дано:

CriteriaQuery<Treatment> cr = cb.createQuery(Treatment.class);
Root<Treatment> root = cr.from(Treatment.class);

Моя попытка была:

if (category != null ) {
    Predicate predicate = cb.or( 
      cb.equal(root.get("product").get("category"), category),
      cb.equal(root.get("product2").get("category"), category)
    );
    predicateList.add(predicate);
}

, но она не сработала: он получает лечение, когда оба продукта не равны нулю, ихотя бы один из них соответствует условию категории.

Сгенерированный запрос был (после очистки, чтобы сделать его читаемым):

select 
  ...
from treatment t 
  cross join product p1 
  cross join product p2 
  where t.product_id=p1.id 
  and t.product2_id=p2.id 
  and (p1.category_id=17 or p2.category_id=17) 
order by t.id desc 

Ответы [ 2 ]

4 голосов
/ 24 сентября 2019

Попробуйте построить пути, используя From#join, где вы можете явно определить тип соединения, например:

Predicate predicate = cb.or( 
  cb.equal(root.join("product", JoinType.LEFT).get("category"), category),
  cb.equal(root.join("product2", JoinType.LEFT).get("category"), category)
);
1 голос
/ 24 сентября 2019

Это должно работать:

Predicate predicate = (root1, cq1, cb1) -> Specifications.where(
            cb1.equal(root1.get("product").get("category"), category)).or(
            cb1.equal(root1.get("product2").get("category"), category))
            .toPredicate(root, cb, cq);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...