在JPQL Query中设置可选参数

时间:2018-05-28 15:07:09

标签: java jpa filter jpql optional-parameters

I got this list of coins that i want to filter with that 3 optional parameters(Currency, quantity and year)

如何将JPQL中的参数设置为可选参数?我不想做9“if else”来检查它是否为null

我得到了函数filtradoMonedas(filterCoins),它使用3个可选参数过滤对象Moneda(硬币),但如果有空参数则无效。

如果不设置空参数,如果cantidad或ano是“”返回错误查询的异常,这只能正常工作。只想把它作为一个可选项。继承人的方法:

public List<Moneda> filtradoMonedas(Divisa divisa, BigDecimal cantidad, 
        BigDecimal ano){

    EntityManager em = getEntityManager();

    Query consulta = em.createQuery("SELECT m FROM Moneda m "
            + "WHERE m.divisa = :divisa "
            + "AND m.cantidad= :cantidad "
            + "AND m.ano = :ano");

    consulta.setParameter("divisa", divisa);
    consulta.setParameter("cantidad", cantidad);
    consulta.setParameter("ano", ano);

    List<Moneda> filtradoMonedas = (List<Moneda>) consulta.getResultList();
    // sincronizar los objetos devueltos con la base de datos
    for (Moneda m : filtradoMonedas) {
        em.refresh(m);
    }

    em.close();
    return filtradoMonedas;
}

2 个答案:

答案 0 :(得分:1)

JPQL不支持可选参数。

实际上你应该认为参数不是可选的,而是条件是可选的。这个想法将引导您创建“动态”查询。这样就会引导您接下来从JPQL切换到Criteria API。这将导致你写这样的东西:

    // Actually can be generated during build, and thus can be ommited
    @StaticMetamodel(Moneda.class)
    abstract class Moneda_ {
        public static volatile SingularAttribute<Moneda, BigDecimal> cantidad;
        public static volatile SingularAttribute<Moneda, Divisia> divisia;
        public static volatile SingularAttribute<Moneda, BigDecimal> ano;
    }

    final CriteriaBuilder cb = em.getCriteriaBuilder();

    final CriteriaQuery<Moneda> cq = cb.createQuery(Moneda.class);
    final Root<Moneda> root = cq.from(Moneda.class);

    Set<Predicate> predicates = new HashSet<>(3);
    if (cantidad != null) {
        predicates.add(cb.equal(root.get(Moneda_.cantidad), cantidad));
    }

    if (ano != null) {
        predicates.add(cb.equal(root.get(Moneda_.ano), ano));
    }

    if (divisia != null) {
        predicates.add(cb.equal(root.get(Moneda_.divisia), divisia));
    }

    cq.where(predicates.toArray(new Predicate[predicates.size()]));

    em.createQuery(cq).getResultList();

    // and do whatever you want 

答案 1 :(得分:1)

在阅读了Ilya Dyoshin的评论和背后的精明思想之后,“您应该认为参数不是可选的,而条件是可选的”。我决定通过使用带有@Query注释的JPQL来实现自己的方式,并创建一个效果很好的动态SQL查询。

关键是应用一些SQL逻辑使条件成为可选条件而不是参数:

    @Query("SELECT a " +
           "FROM amazing " +
           "WHERE (:filterSuperAwesome IS NULL " +
                        "OR a.filterSuperAwesome = :filterSuperAwesome)"); 

    List<FilterSuperAwesome> filterAwesomeORSuperAwesome(
                    @Param("filterSuperAwesome ") FilterSuperAwesome filterSuperAwesome);

请注意,在这里,我基于我的参数可以呈现两种形式(FilterSuperAwesome或NULL实例)的事实使用OR语句。如果为NULL,则条件始终为True,就好像不存在一样。

这在JHipster项目的JpaRepository类中正常工作。