Группировка по дню из даты с помощью JPA Criteria API

155
18 сентября 2021, 05:20

Задача состоит в том, чтобы сгруппировать события по определенному дню, чтобы сделать это, я должен вытащить день из даты и сгруппировать записи по нему. Ранее мы использовали MySql, и этот код работал как следует:

public static Specification<AllFile> findByGroup(FileFilter fileFilter) {
return (Specification<AllFile>) (root, query, cb) -> {
    final Collection<Predicate> predicates = new ArrayList<>();
    if (fileFilter.getStart() != null && fileFilter.getEnd() != null) {
        Date date = new Date(fileFilter.getStart().getTime());
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setDate(1);
        predicates.add(cb.greaterThanOrEqualTo(root.get("created"), date));
        predicates.add(cb.lessThanOrEqualTo(root.get("created"), fileFilter.getEnd()));
    }
    else if(fileFilter.getStart() != null) {
        Date date = new Date(fileFilter.getStart().getTime());
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setDate(1);
        Date newDate = DateUtils.addMonths(date, 1);
        predicates.add(cb.greaterThanOrEqualTo(root.get("created"), date));
        predicates.add(cb.lessThanOrEqualTo(root.get("created"), newDate));
    }
    if (fileFilter.getRoute() != null) {
        predicates.add(cb.equal(root.get("route"), fileFilter.getRoute()));
    }
    if (fileFilter.getDevice() != null) {
        predicates.add(cb.equal(root.get("device"), fileFilter.getDevice()));
    }
    if (fileFilter.getType() != null) {
        predicates.add(cb.equal(root.get("type"), fileFilter.getType()));
    }
    if (fileFilter.getUser() != null) {
        predicates.add(cb.equal(root.get("user"), fileFilter.getUser()));
    }
    if (fileFilter.getDeleted() != null) {
        predicates.add(cb.equal(root.get("deleted"), fileFilter.getDeleted()));
    }

    query.groupBy(cb.function("day", Date.class, root.get("created")));
    return cb.and(predicates.toArray(new Predicate[predicates.size()]));
};

}

Но после перехода на Postgres такой подход работать перестал. для корректной работы мне нужно отправить нечто вроде этого:

select extract(day from allfile0_.created) as dd
from all_file allfile0_ 
where allfile0_.created>='Tue Oct 01 00:00:00 MSK 2019' and 
allfile0_.created<='Fri Nov 01 00:00:00 MSK 2019' 
group by dd

Вместо этого:

select allfile0_.id as id1_0_, allfile0_.added as added2_0_, 
allfile0_.comment as comment3_0_, 
allfile0_.created as created4_0_, allfile0_.deleted as deleted5_0_, 
allfile0_.device_id as 
device_13_0_, allfile0_.duration as duration6_0_, allfile0_.mark as 
mark7_0_, allfile0_.path as 
path8_0_, allfile0_.recognition as recognit9_0_, allfile0_.route_id as 
route_i14_0_, allfile0_.size 
as size10_0_, allfile0_.type as type11_0_, allfile0_.updated as 
updated12_0_, allfile0_.user_id as 
user_id15_0_ 
from all_file allfile0_ 
where allfile0_.created>='Tue Oct 01 00:00:00 MSK 2019' and allfile0_.created<='Fri Nov 01 00:00:00 MSK 2019' 
group by extract(day from allfile0_.created)

Возможно ли получить такой запрос, как мне нужно с помощью Criteria API? Нужен совет по поводу кастомного select, чтобы выбирать именно то что мне нужно.

Answer 1

Изменил

query.groupBy(cb.function("day", Date.class, root.get("created")));

на

query = cb.createTupleQuery();
        root = query.from(AllFile.class);
        query.select(root.get("created")).
                groupBy(cb.function("day", Integer.class, root.get("created")));

после чего код отработал как надо.

READ ALSO
Подскажите пожалуйста, пропустил ли я какой-нибудь пласт информации, или работодатель задал слишком сложный вопрос на позицию Junior Python? [закрыт]

Подскажите пожалуйста, пропустил ли я какой-нибудь пласт информации, или работодатель задал слишком сложный вопрос на позицию Junior Python? [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы на него можно было дать ответ, основанный на фактах и цитатах

132
Как доработать данный код?

Как доработать данный код?

Привет есть такой простой код, при загрузке Дома выполянется функцияКак сделать проверку что если DOM грузится больше 2 секунды, выполнить...

128
Система слота в JavaScript, проблема с if else

Система слота в JavaScript, проблема с if else

Я сделаю что-то типа слот аппарата, все у меня работает кроме одногоУ меня аппарат показывает выигрыш, когда рядом будут 3 одинаковые картинки

98