У меня есть параметры выбора на плоских данных, только не знаю, как полностью опустить параметр или сделать его полным подстановочным знаком. Поиск может использовать один или все параметры. Как это делается? С ANY
ALL
? Или, есть ли другой способ?
Я хотел бы использовать один общий запрос со всеми параметрами и передать "все" или "любые", что-то вдоль этих строк, для некоторых из этих параметров.
существующий код:
package legacy.database;
import java.sql.Timestamp;
import java.util.List;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class MyQueries {
private static final Logger log = Logger.getLogger(MyQueries.class.getName());
private final EntityManagerFactory emf = Persistence.createEntityManagerFactory("LegacyDatabasePU");
private final EntityManager em = emf.createEntityManager();
public MyQueries() {
}
public List<Clients> findAll() {
Query q = em.createQuery("select c from Clients c");
List<Clients> clients = q.getResultList();
return clients;
}
public List<Clients> selectWithParameters(Criteria c) {
log.info(c.toString());
String opener = c.getOpener();
String closer1 = c.getCloser1();
String status = c.getStatus();
Query q = em.createQuery(
"SELECT c FROM Clients c "
+ "WHERE c.status like :status "
+ "and c.closer1 like :closer1 "
+ "and c.opener like :opener");
q.setParameter("opener", opener);
q.setParameter("closer1", closer1);
q.setParameter("status", status);
log.info(q.toString());
List<Clients> clients = q.getResultList();
log.fine(clients.toString());
return clients;
}
public Clients findById(int id) {
Clients client = em.find(Clients.class, id);
return client;
}
public void send(int id) {
Clients c = em.find(Clients.class, id);
java.util.Date date = new java.util.Date();
Timestamp t = new Timestamp(date.getTime());
em.getTransaction().begin();
c.setDateUpdated(t.toString());
em.getTransaction().commit();
}
}
В случае, если параметры являются необязательными, критерии API обеспечивают некоторую гибкость. Если selectWithParameters вызывается часто, рассмотрите возможность использования параметров, так как тогда БД может кэшировать параметризованный запрос.
selectWithParameters с дополнительными параметрами читается следующим образом:
public List<Clients> selectWithParameters(Criteria criteria) {
log.info(criteria.toString());
String opener = criteria.getOpener();
String closer1 = criteria.getCloser1();
String status = criteria.getStatus();
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Clients> query = criteriaBuilder.createQuery(Clients.class);
Root<Clients> c = query.from(Clients.class);
List<Predicate> wherePredicates = new LinkedList<Predicate>();
if (null != status) {
wherePredicates.add(criteriaBuilder.like(c.get("status"), status));
}
if (null != closer1) {
wherePredicates.add(criteriaBuilder.like(c.get("closer1"), closer1));
}
if (null != opener) {
wherePredicates.add(criteriaBuilder.like(c.get("opener"), opener));
}
query.where(wherePredicates.toArray(new Predicate[0]));
List<Clients> clients = em.createQuery(query).getResultList();
log.fine(clients.toString());
return clients;
}
Спасибо, Хайнер. Это сработало, не зная, почему у меня были проблемы с кодом Хайнера, но его образец поставил меня в правильном направлении:
public List<Clients> selectByCriteria(Criteria criteria) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Clients> clientCriteriaQuery = criteriaBuilder.createQuery(Clients.class);
Root<Clients> clientRoot = clientCriteriaQuery.from(Clients.class);
clientCriteriaQuery.select(clientRoot);
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.like(clientRoot.get(Clients_.phone1), "%" + criteria.getPhone1() + "%"));
if (!criteria.getOpener().equalsIgnoreCase("all")) {
predicates.add(criteriaBuilder.like(clientRoot.get(Clients_.opener), "%" + criteria.getOpener() + "%"));
}
if (!criteria.getCloser1().equalsIgnoreCase("all")) {
predicates.add(criteriaBuilder.like(clientRoot.get(Clients_.closer1), "%" + criteria.getCloser1() + "%"));
}
if (!criteria.getStatus().equalsIgnoreCase("all")) {
predicates.add(criteriaBuilder.like(clientRoot.get(Clients_.status), "%" + criteria.getStatus() + "%"));
}
clientCriteriaQuery.where(predicates.toArray(new Predicate[0]));
List<Clients> clients = em.createQuery(clientCriteriaQuery).getResultList();
return clients;
}
Вероятно, нет существенной разницы (?) От того, что ответил Хайнер. JPA и JPQL немного мрачны. Я не могу в это поверить, но я почти предпочитаю SQL! Мне придется приспособиться.