【问题标题】:Dealing with empty or null collection parameter in JPA处理 JPA 中的空或 null 集合参数
【发布时间】:2017-09-19 10:21:21
【问题描述】:

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);

对于 lst = null Hibernate 记录的 Oracle DB:

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&lt;&gt;() Hibernate 的情况:

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


【解决方案1】:

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 在 ANDOR 中支持 null,忽略该表达式,如果您将 IN 运算符构建器放在实用程序函数中,则可以方便地省略空检查。

【讨论】:

    【解决方案2】:

    你可以使用JPANotEmpty or 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);
    }
    

    【讨论】:

    • 我相信你在方法中打错了:省略ratingList,注意methos的名字是findByRatingList...
    猜你喜欢
    • 2021-06-27
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 2016-03-28
    • 1970-01-01
    相关资源
    最近更新 更多