QueryDsl - оператор ИЛИ не работает

У меня есть следующий запрос QueryDSL:

    QCustomer customer = QCustomer.customer;

    BooleanBuilder builder = new BooleanBuilder();
    builder.or(customer.person.name.containsIgnoreCase(query));
    builder.or(customer.company.name.containsIgnoreCase(query));

    return builder;

И я ожидаю получить результаты от лиц, содержащих имя = запрос, и/или компаний, содержащих параметр запроса. Но я ничего не получаю.

Это мое сопоставление класса Customer:

@OneToOne(orphanRemoval = false, optional = true, cascade = CascadeType.ALL)
private Company company;

@OneToOne(orphanRemoval = false, optional = true, cascade = CascadeType.ALL)
private Person person;

Кто-нибудь знает, что мне здесь не хватает?

Я ожидаю получить такой запрос:

select o 
from Customer 
where o.person.name like '%:name%' or o.company.name like '%:name%'

Это сгенерированный запрос:

select 
    count(customer0_.uid) as col_0_0_ 
from 
    Customer customer0_ 
cross join 
    Person person1_ 
cross join 
    Company company2_ 
where 
    customer0_.person_uid=person1_.uid 
    and customer0_.company_uid = company2_.uid 
    and (lower(person1_.name) like ? escape '!' or lower(company2_.name) like ? escape '!') limit ?

Он использует счетчик, потому что это первый запрос, который Spring Data использует для разбиения результата на страницы.


person Deividi Cavarzan    schedule 23.11.2013    source источник
comment
Являются ли и компания, и физическое лицо обязательными свойствами? Вы проверили, как выглядит SQL-запрос?   -  person Timo Westkämper    schedule 23.11.2013
comment
@TimoWestkämper нет, они необязательны ... Я обновил вопрос сгенерированным запросом. спасибо   -  person Deividi Cavarzan    schedule 23.11.2013


Ответы (1)


Запрос выглядит нормально. Скорее всего, вы получите неправильные результаты, потому что неявные соединения на основе свойств делают соединения внутренними.

Используя левые соединения, вы можете получить нужные вам результаты.

QPerson person = QPerson.person;
QCompany company = QCompany.company;
BooleanBuilder builder = new BooleanBuilder();
builder.or(person.name.containsIgnoreCase(str));
builder.or(company.name.containsIgnoreCase(str));

query.from(customer)
     .leftJoin(customer.person, person)
     .leftJoin(customer.company, company)
     .where(builder);
person Timo Westkämper    schedule 23.11.2013
comment
Спасибо за ответ! к сожалению, это не работает. Теперь я понимаю, что Person или Company могут быть нулевыми. Я думаю, что это влияет на запрос. - person Deividi Cavarzan; 23.11.2013
comment
конечно, это влияет на запрос. Все объекты, которые содержат два ненулевых объекта, работают нормально. Знаете ли вы, можно ли обойти эту проблему? - person Deividi Cavarzan; 23.11.2013
comment
Вы получаете те же результаты с моим предложенным запросом? Соединения на уровне SQL должны быть, по крайней мере, левыми соединениями. Не могли бы вы подтвердить? - person Timo Westkämper; 23.11.2013
comment
Это тот же результат. Я создаю список с дополнительной информацией: gist.github.com/cavarzan/7617892 . Проблема в том, что Клиент может быть Лицом или Компанией, а не обоими вместе, поэтому он всегда содержит нулевую ссылку на Лицо или Компанию. - person Deividi Cavarzan; 23.11.2013
comment
Мой плохой Тимо, я использую builder.or(company.person.name.containsIgnoreCase(str)); вместо builder.or(person.name.containsIgnoreCase(str));. Большое спасибо! - person Deividi Cavarzan; 23.11.2013
comment
в случае, если я хочу выполнить левое соединение, например builder.or(company.person.name.containsIgnoreCase(str)); В этом случае запрос возвращает 0 элементов. Есть ли какой-нибудь совет по использованию такого рода дочерних отношений? Спасибо! - person Deividi Cavarzan; 02.06.2014