Как искать в нескольких столбцах, используя один оператор 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();