如何编写处理可选输入参数的 HQL 查询
How to write an HQL query that to handle optional input parameters
@Query("SELECT c FROM message c"
+" WHERE (CASE WHEN a='' THEN 1=1 ELSE a= :a"
+ " WHEN b='' THEN 1=1 ELSE b= :b"
+ " WHEN c='' THEN 1=1 ELSE c= :c"
+ " WHEN d='' THEN 1=1 ELSE d= :d)")
我正在尝试编写一个 HQL 查询,其中 可选 输入值 a、b、c 和 d。
我的目标是让查询识别输入是否为“”,然后仅与 1=1 一起移动,基本上什么都不做。
我一直收到错误
antlr.NoViableAltException:意外标记:=
最初的错误标记是 "CASE",现在是“=”。
“1=1 方法”可行吗?
我可以在 HQL 中使用这样的 CASE 语句吗?
谢谢
更新的尝试:
@Query("SELECT c "
+ "FROM message c"
+ " WHERE"
+ " CASE (WHEN a != '' THEN a = :a"
+ " WHEN b != '' THEN b = :b"
+ " WHEN c != '' THEN c = :c"
+ " WHEN d != '' THEN d = :d)"
antlr.NoViableAltException: unexpected token: WHEN
antlr.NoViableAltException: unexpected token: a
antlr.NoViableAltException: unexpected token: THEN
您确定要使用 JPQL 来执行此操作吗?
我建议你使用 Query By Example
OR QueryDSL
如果您想继续使用 JPQL
,请提前阅读 :P
如果你想使用条件运算符,你可以在@Query
里面使用sPEL
。这是根据您的要求进行的示例查询。
@Query("SELECT C FROM Message C " +
"WHERE 1=1 " +
"AND ((1=:#{ #param1 == null ? 1 : 0 }) OR (C.param1 = :#{#param1})) " +
"AND ((1=:#{ #param2 == null ? 1 : 0 }) OR (C.param2 = :#{#param2})) " +
"AND ((1=:#{ #param3 == null ? 1 : 0 }) OR (C.param3 = :#{#param3})) " +
"AND ((1=:#{ #param4 == null ? 1 : 0 }) OR (C.param4 = :#{#param4})) "
)
List<Message> find(@Param("param1") Long param1, @Param("param2") Long param2,@Param("param3") Long param3, @Param("param4") Long param4);
一点解释
- 第一个条件
1=1
:呵呵,对WHERE
子句下一行的条件很着迷,可以去掉。
((1=:#{ #param1 == null ? 1 : 0 }) OR (C.param1 = :#{#param1}))
: 疯了!!
第一部分将决定是否检查第二部分。假设 param1 是 null
那么 (1=:#{ #param1 == null ? 1 : 0 })
将 return 1=1
和 (C.param1 = :#{#param1})
将被跳过。
- 同样适用于其他条件。
如有任何疑问,请随时发表评论。
顺便说一句,您应该在 JPQL 中使用与对象相关的字段。例如 C.param1
而不仅仅是 param1
.
@Query("SELECT c FROM message c"
+" WHERE (CASE WHEN a='' THEN 1=1 ELSE a= :a"
+ " WHEN b='' THEN 1=1 ELSE b= :b"
+ " WHEN c='' THEN 1=1 ELSE c= :c"
+ " WHEN d='' THEN 1=1 ELSE d= :d)")
我正在尝试编写一个 HQL 查询,其中 可选 输入值 a、b、c 和 d。
我的目标是让查询识别输入是否为“”,然后仅与 1=1 一起移动,基本上什么都不做。
我一直收到错误 antlr.NoViableAltException:意外标记:=
最初的错误标记是 "CASE",现在是“=”。
“1=1 方法”可行吗? 我可以在 HQL 中使用这样的 CASE 语句吗?
谢谢
更新的尝试:
@Query("SELECT c "
+ "FROM message c"
+ " WHERE"
+ " CASE (WHEN a != '' THEN a = :a"
+ " WHEN b != '' THEN b = :b"
+ " WHEN c != '' THEN c = :c"
+ " WHEN d != '' THEN d = :d)"
antlr.NoViableAltException: unexpected token: WHEN
antlr.NoViableAltException: unexpected token: a
antlr.NoViableAltException: unexpected token: THEN
您确定要使用 JPQL 来执行此操作吗?
我建议你使用 Query By Example
OR QueryDSL
如果您想继续使用 JPQL
,请提前阅读 :P
如果你想使用条件运算符,你可以在@Query
里面使用sPEL
。这是根据您的要求进行的示例查询。
@Query("SELECT C FROM Message C " +
"WHERE 1=1 " +
"AND ((1=:#{ #param1 == null ? 1 : 0 }) OR (C.param1 = :#{#param1})) " +
"AND ((1=:#{ #param2 == null ? 1 : 0 }) OR (C.param2 = :#{#param2})) " +
"AND ((1=:#{ #param3 == null ? 1 : 0 }) OR (C.param3 = :#{#param3})) " +
"AND ((1=:#{ #param4 == null ? 1 : 0 }) OR (C.param4 = :#{#param4})) "
)
List<Message> find(@Param("param1") Long param1, @Param("param2") Long param2,@Param("param3") Long param3, @Param("param4") Long param4);
一点解释
- 第一个条件
1=1
:呵呵,对WHERE
子句下一行的条件很着迷,可以去掉。 ((1=:#{ #param1 == null ? 1 : 0 }) OR (C.param1 = :#{#param1}))
: 疯了!!
第一部分将决定是否检查第二部分。假设 param1 是null
那么(1=:#{ #param1 == null ? 1 : 0 })
将 return1=1
和(C.param1 = :#{#param1})
将被跳过。- 同样适用于其他条件。
如有任何疑问,请随时发表评论。
顺便说一句,您应该在 JPQL 中使用与对象相关的字段。例如 C.param1
而不仅仅是 param1
.