如何根据函数的输出在@Query中使用查询字符串

时间:2019-08-27 09:13:49

标签: java spring spring-boot spring-data-jpa spring-data

我正在尝试使用@Query注释进行查询,由于它始终只有一个条件,因此它工作得很好,但是现在我有多个条件,并且希望基于参数动态更改查询字符串。

假设我有2个字符串列表,即listA和listB 我希望查询是

@Query("SELECT l FROM location AS l WHERE l.a IN :listA")

当listA不为空且listB为空时, 和

@Query("SELECT l FROM location AS l WHERE l.b IN :listB")

当listB不为空且listB为空时, 和

@Query("SELECT l FROM location AS l WHERE l.a IN :listA) AND l.b IN :listB"

两个列表都不为空时。

我一直在尝试查看是否可以从其他函数获取查询字符串。

我可以基于列表生成字符串,但是我只是不知道如何将输出字符串放在@Query()中,就像它在存储库界面中一样。

4 个答案:

答案 0 :(得分:1)

使用JPA Specification API link

答案 1 :(得分:1)

您可以使用Specifications来实现。规范类将类似于(假设a,b是文本列):

public class LocationSpecification implements Specification<Location> {
    public LocationSpecification(final List<String> listA, final List<String> listB) {
        this.listA = listA;
        this.listB = listB;
    }

    private final List<String> listA;
    private final List<String> listB;

    @Override
    public Predicate toPredicate(Root<Location> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> predicates = new ArrayList<>();
        if (listA != null) {
            predicates.add(root.<String>get("a").in(listA));
        }
        if (listB != null) {
            predicates.add(root.<String>get("b").in(listB));
        }
        return cb.and(predicates.toArray(new Predicate[0]));
    }
}

存储库需要扩展JpaSpecificationExecutor

public interface LocationRepository 
  extends JpaRepository<Location, Long>, JpaSpecificationExecutor<Location> {}

您会这样称呼它:

List<Location> results = repository.findAll(new LocationSpecification(listA, listB));

P.S。把上面的文字写在我的头顶上,可能需要一些修复。

答案 2 :(得分:0)

您不必始终依靠@Query进行查询。 更好的选择是创建存储过程并根据您的条件以编程方式调用它们。或使用条件动态生成查询like here.

答案 3 :(得分:0)

This article尽管很老,但在标准API / 规格 / Querydsl 之间有很好的概述/比较。 Jooq 是另一个具有免费版本的库。

解决问题的方法是使用其中一种。

我更喜欢Querydsl,因为

  • 这是类型安全的
  • 它与Spring Data配合得很好
  • 您可以在IDE中使用代码完成功能

您还应该考虑(当前)Querydsl维护得不好。