Как фильтровать день, месяц или оба с помощью CriteriaBuilder Java

#java #criteria-api

#java #критерии-api

Вопрос:

кто-нибудь знает, как создать фильтр с помощью CriteriaBuilder?

Я создаю API, и мне нужно создать фильтр для метода списка. В базе данных SQL Server столбец представляет собой smalldatetime, а SQL-запрос, который решает мою проблему, выглядит так:

 SELECT * from TABLE 
where DAY(COLUMN) LIKE 10 AND MONTH(COLUMN) LIKE 5
  

У меня есть класс DTO, который я использую для фильтрации в своем запросе:

 public class MyDTOFilter {
    private Integer day;
    private Integer month;
}
  

Например, если a даст какой-то день = 5, я хотел бы получить этот ответ:

«2020-01-05»
«2020-02-05»
«2019-10-05″…

Если указать оба, например, месяц = 1 и день = 10, я хотел бы получить этот ответ:

«2020-01-10»
«2019-01-10»
«2018-01-10″…

Как я могу это сделать, используя CriteriaBuilder на Java?

Спасибо вам всем.

Ответ №1:

Поскольку CriteriaBuilder не имеет специализированных функций базы данных, вам необходимо вызвать эти функции по имени:

 // DAY(COLUMN) returns an int
criteriaBuilder.function("DAY", Integer.class, "COLUMN")
// or, with JPA metamodel
criteriaBuilder.function("DAY", Integer.class, Entity_.column)
  

Результат должен быть примерно таким:

 public List<LocalDate> findDates(int day, int month) {
  CriteriaQuery<LocalDate> query = criteriaBuilder.createQuery(LocalDate.class);
  Root<Entity> root = query.from(Entity.class);
  query.select(root.get(Entity_.column));
  List<Predicate> predicates = new ArrayList<>();
  ParameterExpression<Integer> dayParameter = null;
  ParameterExpression<Integer> monthParameter = null;
  if (day > 0) {
    dayParameter = criteriaBuilder.parameter(Integer.class);
    predicates.add(
      criteriaBuilder.equal(
        criteriaBuilder.function("DAY", Integer.class, root.get(Entity_.column)),
          dayParameter ));
  }
  if (month > 0) {
    monthParameter = criteriaBuilder.parameter(Integer.class);
    predicates.add(
      criteriaBuilder.equal(
        criteriaBuilder.function("MONTH", Integer.class, root.get(Entity_.column)),
        monthParameter ));
  }
  if (!predicates.isEmpty()) {
    query.where(criteriaBuilder.and(
      predicates.toArray(new Predicate[predicates.size()])));
  }
  TypedQuery<GregorianCalendar> typedQuery = getEntityManager().createQuery(query);
  if (dayParameter != null) {
    typedQuery.setParameter(dayParameter, day);
  }
  if (monthParameter != null) {
    typedQuery.setParameter(monthParameter, month);
  }
  return typedQuery.getResultList();
}
    
  

Комментарии:

1. Я понимаю, в чем тут дело, я использую спецификацию<T> и попытался помочь вам, но я получаю другую ошибку: code org.springframework.dao.InvalidDataAccessApiUsageException: Unable to locate Attribute with the the given name code` Вот суть метода: link Мой класс DateFilter имеет два атрибута: частный целочисленный день; частный целочисленный месяц; Вы знаете, как это сделать?

2. Прокомментировал там @Neil