通过用户定义的动态where子句条件

时间:2015-06-17 19:06:06

标签: java mysql jpa orm eclipselink

我想创建一个用户定义where子句条件的搜索。如果用户在搜索表单中输入参数,则该参数包含在WHERE子句中。如果参数留空,则从where子句中省略。如果整个表单为空,则查询应返回SELECT ALL和整个表。以这种方式,查询逐渐变得更精确,用户输入的参数越多。

我正在尝试以下代码,但这似乎需要输入参数并仅在实际数据与指定的所有Predicates匹配时返回结果。看起来Predicates包含在数组中,即使它们是NULL并且为空?无论是那个,还是我都错过了一些非常明显的东西。

我的问题是:

1)如果搜索表单留空,是否会从数组中排除谓词?

2)如果是,请问查询默认为SELECT ALL吗? [query.from(Contacts.class)]

我看到了一个类似的问题,但并没有真正告诉我如何实现上述目标,因为看起来我的代码逻辑是正确的。

JPA where clause any

提前感谢任何指导!

public ListDataModel<Contacts> qSearchContacts(String firstName, String surName, Integer countryid, Integer companyId) {

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Contacts> query = cb.createQuery(Contacts.class);
    Root<Contacts> cont = query.from(Contacts.class);
    query.select(cont);

    List<Predicate> predicateList = new ArrayList<Predicate>();
    Predicate firstnamePredicate, surnamePredicate, countryPredicate, companyPredicate;

    if ((firstName != null) && (!(firstName.isEmpty()))) {
        firstnamePredicate = cb.like(cb.upper(cont.<String>get("firstName")), "%" + firstName.toUpperCase() + "%");
        predicateList.add(firstnamePredicate);
    }


    if ((surName != null) && (!(surName.isEmpty()))) {
        surnamePredicate = cb.like(cb.upper(cont.<String>get("surName")), "%" + surName.toUpperCase() + "%");
        predicateList.add(surnamePredicate);

     }

    if (countryid != null) {
        Join<Contacts, Country> country = cont.join("country");
        countryPredicate = cb.equal(country.<Integer>get("countryid"), countryid);
        predicateList.add(countryPredicate);
    } 
    }

    if (companyId != null) {
        Join<Contacts, Company> company = cont.join("company");
        companyPredicate = cb.equal(company.<Integer>get("companyId"), companyId);
        predicateList.add(companyPredicate);
    }

    Predicate[] predicateArray = new Predicate[predicateList.size()];
    predicateList.toArray(predicateArray);
    query.where(predicateArray);
    ListDataModel<Contacts> contactResultList = new ListDataModel<Contacts>(em.createQuery(query).getResultList());

    return contactResultList;
}

1 个答案:

答案 0 :(得分:0)

我解决了这个问题。上面的代码似乎在所有情况下创建谓词,并且没有明确的条件从数组列表中排除谓词或在没有谓词存在的情况下执行SELECT ALL。我使用TypedQuery对象显式地重写了每个参数的代码。现在这导致了期望的行为。没有谓词导致SELECT ALL。如果每个谓词不为null且为空,则它们仅作为WHERE子句条件包含在内。希望这可以帮助。

public ListDataModel<Contacts> qSearchContacts(String firstName, String surName, Integer countryid, Integer companyId) {

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Contacts> query = cb.createQuery(Contacts.class);
    Root<Contacts> cont = query.from(Contacts.class);
    query.select(cont);

    // Join<Contacts, Country> country = cont.join("country", JoinType.LEFT);
    List<Predicate> predicateList = new ArrayList<Predicate>();

    if ((firstName != null) && (!(firstName.isEmpty()))) {
        ParameterExpression<String> p
                = cb.parameter(String.class, "firstName");
        predicateList.add(cb.like(cb.upper(cont.<String>get("firstName")), "%" + firstName.toUpperCase() + "%"));

    }

    if ((surName != null) && (!(surName.isEmpty()))) {
        ParameterExpression<String> p
                = cb.parameter(String.class, "surName");
        predicateList.add(cb.like(cb.upper(cont.<String>get("surName")), "%" + surName.toUpperCase() + "%"));

    }

    if ((countryid != null) && (countryid != 0)) {
        Join<Contacts, Country> country = cont.join("country");
        ParameterExpression<Integer> ci
                = cb.parameter(Integer.class, "countryid");
        predicateList.add(cb.equal(country.get("countryid"), ci));
    }

    if ((companyId != null) && (companyId != 0)) {
        Join<Contacts, Company> company = cont.join("company");
        ParameterExpression<Integer> co
                = cb.parameter(Integer.class, "companyId");
        predicateList.add(cb.equal(company.get("companyId"), co));
    }

    if (predicateList.size() == 0) {
        query.select(cont);
    } else {
        if (predicateList.size() == 1) {
            query.where(predicateList.get(0));
        } else {
            query.where(cb.and(predicateList.toArray(new Predicate[0])));
        }
    }

    TypedQuery<Contacts> tq = em.createQuery(query);
    if (firstName != null) {
        tq.setParameter("firstName", firstName);
    }
    if (surName != null) {
        tq.setParameter("surName", surName);
    }

    if ((countryid != null) && (countryid != 0)) {
        tq.setParameter("countryid", countryid);
    }

    if((companyId != null) && (companyId != 0)) {
        tq.setParameter("companyId", companyId);
    }

    ListDataModel<Contacts> contactsResultList = new ListDataModel<Contacts>(tq.getResultList());
    return contactsResultList;

}
}