我正在尝试使用@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()中,就像它在存储库界面中一样。
答案 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,因为
您还应该考虑(当前)Querydsl维护得不好。