处理 JPA 中的空集合参数

问题描述 投票:0回答:2

内部

org.springframework.data.jpa.repository.@Query
注释我检查集合中的字段是否为空,如果集合为空则可能忽略集合:

@Query(""select e from #{#entityName} where e.type in :lst or 0 = :lstSize")
List<Entity> findByLst(@Param("lst") List<XEnum> lst, @Param("lstSize") int lstSize);

我称代码为:

List<XEnum> lst = ...;
int lstSize = (lst == null) ? 0 : lst.size();
findByLst(lst, lstSize);

对于 Oracle DB 在

lst = null
Hibernate 记录的情况下:

DEBUG [nio-8443-exec-4] org.hibernate.SQL
entity0_.type in (?) or 0=?
TRACE [nio-8443-exec-4] org.hibernate.type.EnumType
Binding null to parameter: [1]
TRACE [nio-8443-exec-4] org.hibernate.type.descriptor.sql.BasicBinder
binding parameter [2] as [INTEGER] - [0]

对于

lst = new LinkedList<>()
休眠记录的情况:

DEBUG [nio-8443-exec-5] org.hibernate.SQL
entity0_.type in ( ) or 0=?
TRACE [nio-8443-exec-5] org.hibernate.type.descriptor.sql.BasicBinder
binding parameter [1] as [INTEGER] - [0]
ERROR [nio-8443-exec-5] org.hibernate.engine.jdbc.spi.SqlExceptionHelper
ORA-00936: missing expression

它在 SQL*PLUS 中在句法上也是无效的:

select 1 from dual where 1 in ();

我可以省略

lstSize
并仍然检查是否未提供集合 - 返回所有元素吗?

如何处理空列表和 Oracle

()
语法错误?

实际上我有一个很大的 JPQL 表达式,可以通过一次调用处理多个空参数的情况。我的目标是保持简单的方法,而不是编写几个专门的方法,使用

if/else
或Critetia builder ...

例如忽略空参数可以归档:

 ... and (e.field = :fieldVal or :fieldVal is null)

更新相关资源:

hibernate jpa spring-data spring-data-jpa jpql
2个回答
0
投票

Criteria API 用于救援。

您正在动态构建 SQL 查询(当您通过构建工具插件从实体生成特殊类时,有可能工作类型安全)。

Spring Data 以

org.springframework.data.jpa.domain.Specification
+
org.springframework.data.jpa.repository.JpaSpecificationExecutor
的形式提供便利,所以查询可能看起来像:

Specification<Book> spec = (Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
    ...
    if (CollectinUtils.isNotEmpty(ids)) {
        root.get("id").in(ids);
    }
}
List<Book> booksByIds = repository.findAll(spec);

Hibernate Criteria API 支持

null
中的
AND
OR
忽略该表达式,如果您将
IN
运算符构建器放入实用程序函数中,则可以方便地省略空检查。


0
投票

您可以使用 JPA NotEmpty 或 IsNotEmpty

示例代码

实体

public class products{
  ....fields

  @OneToMany(mappedBy = "productId")
  @JsonIgnore
  private List<Rating> ratingList;

  .....geter/setter
}


public class Rating{
  ....fields
 
 @JoinColumn(name = "product_id", referencedColumnName = "id")
 @ManyToOne
 @JsonIgnore
 private Products productId;

  .....geter/setter

}

资料库

public interface ProductRepository extends JpaRepository<Products, Integer>{
   public Page<Products> findByRatingListNotEmpty(Pageable pg);
}
© www.soinside.com 2019 - 2024. All rights reserved.