Как я прокомментировал в (в настоящее время) принятом ответе, есть ловушка, использующая, с одной стороны, функцию lower()
СУБД, а с другой стороны, String.toLowerCase()
java, так как оба метода не гарантируют одинаковый вывод длята же строка ввода.
Наконец-то я нашел гораздо более безопасное (но не пуленепробиваемое) решение, которое позволяет СУБД выполнять все понижения, используя буквальное выражение:
builder.lower(builder.literal("%" + keyword + "%")
Так чтоПолное решение будет выглядеть так:
query.where(
builder.or(
builder.like(
builder.lower(
root.get(
type.getDeclaredSingularAttribute("username", String.class)
)
), builder.lower(builder.literal("%" + keyword + "%")
),
builder.like(
builder.lower(
root.get(
type.getDeclaredSingularAttribute("firstname", String.class)
)
), builder.lower(builder.literal("%" + keyword + "%")
),
builder.like(
builder.lower(
root.get(
type.getDeclaredSingularAttribute("lastname", String.class)
)
), builder.lower(builder.literal("%" + keyword + "%")
)
)
);
Редактировать:
Когда @cavpollo попросил меня привести пример, мне пришлось дважды подумать о своем решении и понять, что оно не намного безопаснее, чем принятый ответ:
DB value* | keyword | accepted answer | my answer
------------------------------------------------
elie | ELIE | match | match
Élie | Élie | no match | match
Élie | élie | no match | no match
élie | Élie | match | no match
Тем не менее, я предпочитаю свое решение, так как оно не сравнивает результаты двух разных функций, которые должны работать одинаково.Я применяю одну и ту же функцию ко всем массивам символов, чтобы сравнение результатов стало более «стабильным».
Пуленепробиваемое решение будет включать в себя локаль, так что lower()
SQL сможет корректно опускать символы с ударением.(Но это выходит за рамки моих скромных знаний)
* Значение в дБ с PostgreSQL 9.5.1 с языком 'C'