我有一个查询,它应该根据各种参数进行筛选;这些参数之一是列表,如果列表中存在条目,则应该基于条目进行过滤;但如果列表为空/null,则不应对该字段进行任何过滤。
我的想法是这样的:
@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);
发送空List会抛出NPE;发送一个空列表时,它会生成以下无效的SQL
where alert0_.date >= '2018-01-01' and
((1, 123) is null or alert0_.countryId in (1, 123))
我也尝试过在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)
或使用拼写:"and (:#{countryIds.size() > 0} or (a.countryId in (:countryIds))) "
,但同样,它不编译JPQL。
我想到的唯一解决方案是动态生成JPQL,这很难看,或者填充countryIds
和siteTypeIds
的所有现有值,这效率很低。
JPA实现是Hibernate,数据库是MySQL。
4条答案
按热度按时间mspsb9vt1#
经过大量的试验和错误,我发现一个可以接受的工作解决方案与Spel;认为有些人可能会觉得有用
作为参数发送的集合必须是
null
,而不是空集。这将生成可接受的SQL:llmtgqce2#
我有同样的问题,所以我写扩展的解决方案也使用嵌入式参数
其中suppliers可为null、为空或包含值,productIdentifier是包含productNumber和manufacturerId的嵌入ID,传递为
间隔也是有效的,从fromDate到null(永远)或untilDate。
8ulbf1ek3#
对于我来说,这种情况下的最佳解决方案是标准API,如果你不熟悉它,你可以在这里找到一些信息:
https://www.objectdb.com/java/jpa/query/criteria
4urapxun4#
经过一些尝试和错误,我得到了这个工作的那些谁想要处理空列表时,使用IN JPA子句.如果有至少一个元素,它过滤正常,否则,它会带来整个结果集,如果集合是空的:
在Eclipselink 2.7.11.v20220804- 52 dea 2a 3c 0+Spring数据-jpa 2.7.7上运行此代码