JPA规范和.where子句中的空参数

x33g5p2x  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(197)

我写了两个Specifications,如果它们的参数为null,则返回null。

public static Specification<Prodotto> getProdottoByLineaSpec (String linea) {

        if (linea != null) {
            return (root, query, criteriaBuilder) -> {
                return criteriaBuilder.like((root.join("linea")).get("nome"), "%"+linea+"%");
            };
        }
        else return null;
    }

public static Specification<Prodotto> getProdottoByIngSpec (String ing) {

        if (ing != null) {
            return (root, query, criteriaBuilder) -> {
                return criteriaBuilder.like(((root.join("listaQuoteIng")).join("ing")).get("nome"), "%"+ing+"%");
            };
        }
        else return null;
    }

然后我创建了第三个,它将前面的语句与where子句中的and操作符结合起来:

public static Specification<Prodotto> getProdottoByMainTraits (String linea, String ing) {

        return Specification.where(getProdottoByLineaSpec(linea).and(getProdottoByIngSpec(ing)));
    }

这才是有趣的地方

  • 如果ByLinea返回null,则在解析where子句时,我将从checkPackageAccess获得nullPointerException
  • 如果ByIng返回null,它将被忽略(就像它应该被忽略一样),查询将只匹配另一个 predicate 。
  • 如果我交换两个 predicate ,把ByIng作为第一个 predicate ,然后把ByLinea放在where子句中,那么在每个组合中一切都正常。
vltsax25

vltsax251#

避免从方法返回null是一个很好的做法。
可以使用criteriaBuilder .conjunction()忽略null参数Specification。它总是生成truePredicate。还有一个相反的方法criteriaBuilder .disjunction()

public static Specification<Prodotto> getProdottoByLineaSpec (String linea) {
                        
    return (root, query, criteriaBuilder) -> {
        if (linea == null) {                 
            return criteriaBuilder.conjunction();
        }

        return criteriaBuilder.like(
                 (root.join("linea")).get("nome"), 
                 "%" + linea + "%"
        );            
    }
}

另外,如果第一个Specificationnull试图访问and方法,则会得到NullPointerException

Specification.where(null.and(getProdottoByIngSpec(ing)));

但是如果第二个Specificationnull,这个就可以了

Specification.where(getProdottoByLineaSpec(linea).and(null));

因为方法参数可以是null

相关问题