установить параметр, который является нулевым в @NamedQuery (JPA QL 1.0) - PullRequest
2 голосов
/ 02 июня 2011

Я пишу именованный запрос JPA QL, который будет искать документы. Это должно быть сделано только в одном запросе, и я не могу переключиться на собственный SQL (это не функциональное требование). Написанный мною запрос выглядит следующим образом:

query = "select doc from Doc doc " +
" join doc.Csts cst " +
" where cst.cstFrstNm like :FrstNm " +
" and cst.cstLastNm like :LastNm " +
" and doc.resId = :id ";

Этот запрос параметризован с использованием следующих инструкций:

query.setParameter("FrstNm ", firstName + '%');
query.setParameter("LastNm ", lastName + '%');            
query.setParameter("id", resId);

firstName, lastName, resId в приведенном выше коде мои критерии поиска, и все они являются строками, и они могут быть нулевыми. Когда один из них имеет значение null, это не должно учитываться при вызове запроса.

Например:

Допустим, что: firstName = "John", lastName = "Doe" и resId равны нулю, тогда запрос должен вернуть все записи из таблицы Doc, предназначенные для пользователя John Doe, независимо от их resId. *

Я пытался вставить в запрос дополнительные условия ИЛИ и И, которые бы проверяли, имеет ли resId значение NULL, но это не сработало. Я тестирую его на HSQLDB.

Есть ли способ изменить этот запрос JPA для обработки нулевых значений?

Ответы [ 2 ]

3 голосов
/ 02 июня 2011

Два решения:

Первое, не используйте именованный запрос и создайте новый запрос для каждого запроса:

boolean first = true;
query = query = "select doc from Doc doc " +
" join doc.Csts cst " +
if (firstName != null) {
    query += (first ? " where " : " and ");
    query += " cst.cstFrstNm like :FrstNm ";
    first = false;
}
query += ";";
// ...

Второе решение, вы используете подстановочный знак.Если ваш параметр пуст, просто добавьте «%» в ваш запрос, который будет соответствовать всем соответствующим строкам:

query.setParameter("FrstNm ", (firstName != null ? firstName : "") + '%');
query.setParameter("LastNm ", (lastName != null ? lastName : "") + '%');

Если firstName пусто, ваш запрос будет выглядеть так:

... cst.cstFrstNm like '%' ...

и будет соответствовать всем значениям.Это приведет к тому, что параметр не будет фильтровать какой-либо результат с поведением, аналогичным тому, как если бы его не было.

1 голос
/ 02 июня 2011

Вам может потребоваться построить запрос динамически, чтобы удовлетворить ваши параметры. Например:

public List<Employee> findEmployees(String name, String deptName, String projectName, String city) {
  StringBuffer query = new StringBuffer();
  query.append("SELECT DISTINCT e ");
  query.append("FROM Employee e LEFT JOIN e.projects p ");
  query.append("WHERE ");
  List<String> criteria = new ArrayList<String>();
  if (name != null) { criteria.add("e.name = :name"); }
  if (deptName != null) { criteria.add("e.dept.name = :dept"); }
  if (projectName != null) { criteria.add("p.name = :project"); }
  if (city != null) { criteria.add("e.address.city = :city"); }
  if (criteria.size() == 0) {
     throw new RuntimeException("no criteria");
  }
  for (int i = 0; i < criteria.size(); i++) {
    if (i > 0) { query.append(" AND "); }
       query.append(criteria.get(i));
  }
  Query q = em.createQuery(query.toString());
  if (name != null) { q.setParameter("name", name); }
  if (deptName != null) { q.setParameter("dept", deptName); }
  if (projectName != null) { q.setParameter("project", projectName); }
  if (city != null) { q.setParameter("city", city); }
  return (List<Employee>)q.getResultList();
}

Вы также хотите рассмотреть Criteria API, если вы используете JPA 2.0 для такого рода задач.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...