m3t*_*man 5 java spring hibernate jpa spring-data-jpa
我有一个查询应该根据各种参数进行过滤;这些参数之一是列表。如果列表中有条目,则应该根据条目进行过滤;但如果列表为空/空,则不应对该字段进行任何过滤。
我的想法是这样的:
@Query("select a from Alert a where a.date >= :startDate " +
"and (((:countryIds) is null) or a.countryId in (:countryIds)) " +
"and (((:typeIds) is null) or a.siteTypeId in (:typeIds)) ")
List<Alert> findBy(@Param("startDate") Date startDate,
@Param("countryIds") Set<Long> countryIds,
@Param("typeIds") Set<Long> typeIds);
Run Code Online (Sandbox Code Playgroud)
发送 null List 会抛出 NPE;发送一个空列表会生成以下 SQL,这是无效的
where alert0_.date >= '2018-01-01' and
((1, 123) is null or alert0_.countryId in (1, 123))
Run Code Online (Sandbox Code Playgroud)
我也尝试过在 JPQL 中使用and (((:countryIds) is empty) or a.countryId in (:countryIds)),但在尝试编译 JPQL(在应用程序启动时)时它也不起作用:Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: ??? is not mapped
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:171)
或使用 SpEL:
"and (:#{countryIds.size() > 0} or (a.countryId in (:countryIds))) "
但同样,它不会编译 JPQL。
我想到的唯一解决方案是动态生成 JPQL,这很丑陋,或者填充所有现有值,countryIds但siteTypeIds效率很低。
JPA实现是Hibernate,数据库是MySQL。
m3t*_*man 12
经过大量的试验和错误,我找到了一个可以接受的 SpEL 工作解决方案;认为有些人可能会觉得它有用:
@Query("select a from Alert a where a.date >= :startDate "
"and (:#{#countryIds == null} = true or (a.countryId in (:countryIds))) " +
"and (:#{#siteTypeIds == null} = true or (a.siteTypeId in (:siteTypeIds))) ")
List<Alert> findBy(@Param("startDate") Date startDate,
@Param("countryIds") Set<Long> countryIds,
@Param("siteTypeIds") Set<Long> siteTypeIds);
Run Code Online (Sandbox Code Playgroud)
作为参数发送的集合必须null代替空集合。它产生可接受的 SQL:
select alert0_.alertId as alertId1_0_, [...]
from alert alert0_
where alert0_.date >= '2018-01-01' and
(0 = 1 or alert0_.countryId in (1, 123)) and
(1 = 1 or alert0_.siteTypeId in (null));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4829 次 |
| 最近记录: |