Как искать в нескольких столбцах, используя один оператор like в HQL (hibernate sql)

Надеюсь, что кто-то может помочь мне с этим запросом HQL.

Я использую:

Query query = session.createQuery(sql);

где sql:

select distinct c.id from EstateConsumer as c where c.clientId = ? and  (c.vehicleReg1 or c.vehicleReg2) like ?

но получает следующее исключение:

org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: or near line 1, column 121

Итак, как вы можете использовать синтаксис "ИЛИ", используя один "как"?

Следующее однако работает:

select distinct c.id from EstateConsumer as c where c.clientId = ? and  c.vehicleReg1 like ? or c.vehicleReg2 like ?

но я не хочу использовать несколько "лайков"

2 ответа

Решение

Вы можете решить свою проблему с помощью REGEX, например:

REGEXP_LIKE('Hello world', 'Hello', 'mars') = 1

Таким образом, вы можете заменить свой запрос:

select ... where c.clientId = ? and  c.vehicleReg1 like ? or c.vehicleReg2 like ?

используя этот запрос здесь:

SELECT ... WHERE c.clientId = ? and REGEXP_LIKE(?, c.vehicleReg1, c.vehicleReg2) = 1
-- -------------------------------------^^

Это значит, если ваша ценность ? как c.vehicleReg1 или же c.vehicleReg2 вернуть 1 иначе совпадение неверно


Заметка

@mm759, из-за того, как программа закодирована и структурирована... она передает только 2 параметра (один для clientId и один для нескольких столбцов vehicleReg)

Вы можете использовать один и тот же параметр в нескольких позициях в вашем запросе, например так:

q = getEntityManager().createNamedQuery(
"select ... where c.clientId = :par1 and  c.vehicleReg1 like :par2 or c.vehicleReg2 like :par2");
//-------------------------------^^----------------------------^^--------------------------^^

q.setParamettre("par1", "value1");
q.setParamettre("par2", "value2");

Сложный вариант, такой как вариант regexp_like, предложенный @YCF_L, вероятно, включает дополнительные издержки производительности, хотя бы потому, что СУБД испытывает проблемы с оптимизацией такого запроса в той же степени, что и при использовании "знакомых" операторов.

Я бы пошел на решение, где вы повторно используете параметр.

Вы заявляете,

из-за того, как программа закодирована и структурирована... она передает только 2 параметра (один для clientId и один для нескольких столбцов vehicleReg)

Я не понимаю, почему вы не можете просто захватить один из параметров и использовать его повторно. YCL_F приводит очень хороший пример этого в своем обновлении, но если вы используете JPA, почему бы не перейти на полное решение JPA? Это дает дополнительные преимущества в том смысле, что он безопасен для типов, безопасен для рефакторинга и может (лучше) кэшироваться, чем собственный SQL-запрос.

Например,

CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<C> jpaquery = cb.createQuery(C.class);
Root<C> root = jpaquery.from(C.class);

jpaquery.where(cb.and(cb.equal(root.get(C_.clientId), parameter1),cb.or(cb.like(root.get(C_.vehicleReg1), parameter2), cb.like(root.get(C_.vehicleReg2), parameter2)));
jpaQuery.select(...);

return getEntityManager().createQuery(jpaQuery).getResultList();
Другие вопросы по тегам