如何在HQL中使用一个类似的运算符搜索多列(hibernate sql)

时间:2017-03-13 07:31:18

标签: java sql hibernate hql

希望有人可以帮我解决这个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

那么如何使用“赞”来使用“OR”语法?

以下情况有效:

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

但我不想使用多个“喜欢”的

2 个答案:

答案 0 :(得分:3)

您可以使用 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.vehicleReg1c.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");

答案 1 :(得分:1)

一个复杂的变体,例如@YCF_L提出的regexp_like变体,可能包括额外的性能开销,只是因为DBMS无法将这样的查询优化到与使用“熟悉的”运算符的查询相同的程度。

我会寻求重用参数的解决方案。

你说,

  

由于程序编码和结构化的方式......它只传递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();