是否可以创建动态 JPQL 查询?
Is it possible to create a dynamic JPQL query?
我需要创建一个动态查询。我尝试使用 JPQL 来做到这一点,但做不到。
例如:
public List get(String category, String name, Integer priceMin, Integer priceMax){
List<Prod> list;
String query = "select p from Prod p where 1<2 ";
String queryCat="";
String queryName="";
String queryPriceMin="";
String queryPriceMax="";
String and = " and ";
if (!category.isEmpty()){
query+=and+"p.cat.name=:category ";
}
if (!name.isEmpty()){
query+=and+"p.name=:name ";
}
if (priceMin!=null){
query+=and+"p.price>=:priceMin ";
}
if (priceMax!=null){
query+=and+"p.price<=:priceMax ";
}
return list = entityManager.createQuery(query)
.setParameter("category", category)
.setParameter("name",name)
.setParameter("priceMin", priceMin)
.setParameter("priceMax", priceMax)
.getResultList();
}
如果有所有参数,查询运行,但如果没有这样的参数 category
我有异常 java.lang.IllegalArgumentException: Parameter with that name [category] did not exist
我明白为什么会这样,但我如何避免这种情况有问题吗?
你可以试试
public List<Prod> get(String category, String name, Integer priceMin, Integer priceMax){
Map<String, Object> paramaterMap = new HashMap<String, Object>();
List<String> whereCause = new ArrayList<String>();
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("select p from Prod p ");
if (!category.isEmpty()){
whereCause.add(" p.cat.name =:category ");
paramaterMap.put("category", category);
}
if (!name.isEmpty()){
whereCause.add(" p.name =:name ");
paramaterMap.put("name", name);
}
if (priceMin!=null){
whereCause.add(" p.price>=:priceMin ");
paramaterMap.put("priceMin", priceMin);
}
if (priceMax!=null){
whereCause.add("p.price<=:priceMax ");
paramaterMap.put("priceMax", priceMax);
}
//.................
queryBuilder.append(" where " + StringUtils.join(whereCause, " and "));
Query jpaQuery = entityManager.createQuery(queryBuilder.toString());
for(String key :paramaterMap.keySet()) {
jpaQuery.setParameter(key, paramaterMap.get(key));
}
return jpaQuery.getResultList();
}
您可以使用 JpaSpecificationExecutor
我会用我的例子来解释它。
在存储库中
public interface ABCRepository extends JpaRepository<ABC, UUID> , JpaSpecificationExecutor<Event> {
}
在服务方法中,您可以按如下方式使用它
public 列表搜索(EventSearch eventSearch) {
return eventRepository.findAll(new Specification<Event>(){
@Override
public Predicate toPredicate(Root<Event> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if(!eventSearch.getTitle().equals(null)) {
predicates.add(criteriaBuilder.like(root.get("title"), "%" + eventSearch.getTitle() + "%"));
}
if(!eventSearch.getLocation().equals(null)) {
predicates.add(criteriaBuilder.like(root.get("location"), "%" + eventSearch.getLocation() + "%"));
}
if(!eventSearch.getStartDate().equals(null)){
predicates.add(criteriaBuilder.greaterThan(root.get("startDate"), eventSearch.getStartDate()));
}
if(!eventSearch.getEndDate().equals(null)){
predicates.add(criteriaBuilder.greaterThan(root.get("endDate"), eventSearch.getEndDate()));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
});
}
我需要创建一个动态查询。我尝试使用 JPQL 来做到这一点,但做不到。 例如:
public List get(String category, String name, Integer priceMin, Integer priceMax){
List<Prod> list;
String query = "select p from Prod p where 1<2 ";
String queryCat="";
String queryName="";
String queryPriceMin="";
String queryPriceMax="";
String and = " and ";
if (!category.isEmpty()){
query+=and+"p.cat.name=:category ";
}
if (!name.isEmpty()){
query+=and+"p.name=:name ";
}
if (priceMin!=null){
query+=and+"p.price>=:priceMin ";
}
if (priceMax!=null){
query+=and+"p.price<=:priceMax ";
}
return list = entityManager.createQuery(query)
.setParameter("category", category)
.setParameter("name",name)
.setParameter("priceMin", priceMin)
.setParameter("priceMax", priceMax)
.getResultList();
}
如果有所有参数,查询运行,但如果没有这样的参数 category
我有异常 java.lang.IllegalArgumentException: Parameter with that name [category] did not exist
我明白为什么会这样,但我如何避免这种情况有问题吗?
你可以试试
public List<Prod> get(String category, String name, Integer priceMin, Integer priceMax){
Map<String, Object> paramaterMap = new HashMap<String, Object>();
List<String> whereCause = new ArrayList<String>();
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("select p from Prod p ");
if (!category.isEmpty()){
whereCause.add(" p.cat.name =:category ");
paramaterMap.put("category", category);
}
if (!name.isEmpty()){
whereCause.add(" p.name =:name ");
paramaterMap.put("name", name);
}
if (priceMin!=null){
whereCause.add(" p.price>=:priceMin ");
paramaterMap.put("priceMin", priceMin);
}
if (priceMax!=null){
whereCause.add("p.price<=:priceMax ");
paramaterMap.put("priceMax", priceMax);
}
//.................
queryBuilder.append(" where " + StringUtils.join(whereCause, " and "));
Query jpaQuery = entityManager.createQuery(queryBuilder.toString());
for(String key :paramaterMap.keySet()) {
jpaQuery.setParameter(key, paramaterMap.get(key));
}
return jpaQuery.getResultList();
}
您可以使用 JpaSpecificationExecutor 我会用我的例子来解释它。
在存储库中
public interface ABCRepository extends JpaRepository<ABC, UUID> , JpaSpecificationExecutor<Event> {
}
在服务方法中,您可以按如下方式使用它
public 列表搜索(EventSearch eventSearch) {
return eventRepository.findAll(new Specification<Event>(){
@Override
public Predicate toPredicate(Root<Event> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if(!eventSearch.getTitle().equals(null)) {
predicates.add(criteriaBuilder.like(root.get("title"), "%" + eventSearch.getTitle() + "%"));
}
if(!eventSearch.getLocation().equals(null)) {
predicates.add(criteriaBuilder.like(root.get("location"), "%" + eventSearch.getLocation() + "%"));
}
if(!eventSearch.getStartDate().equals(null)){
predicates.add(criteriaBuilder.greaterThan(root.get("startDate"), eventSearch.getStartDate()));
}
if(!eventSearch.getEndDate().equals(null)){
predicates.add(criteriaBuilder.greaterThan(root.get("endDate"), eventSearch.getEndDate()));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
});
}