JPA Criteria API
Выборка записей с максимальной датой в разрезе значений определённого поля
На SQL выражение выглядит так (записи с максимальным create_timestamp у каждого sender’а):
select * from
incoming_swift oq
join
(
select
max(create_timestamp) as create_timestamp, sender
from
incoming_swift
group by sender
) sq
on oq.sender = sq.sender and oq.create_timestamp = sq.create_timestamp;
Но т.к. criteria api поддерживает подзапросы полько в секции where, то можно реализовать только такой запрос (будет делать то же самое):
select
*
from
incoming_swift oq
where
(
select
max(sq.create_timestamp)
from
incoming_swift sq
where
sq.sender=oq.sender
)=oq.create_timestamp;
Если реализовать интерфейс Specification, то он будет выглядеть так:
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;
public class SwiftSpecification implements Specification<IncomingSwift> {
private final GetSwiftRequestDto dto;
public SwiftSpecification(GetSwiftRequestDto dto) {
this.dto = dto;
}
@Override
public Predicate toPredicate(Root<IncomingSwift> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicateList = new ArrayList<>();
Subquery<LocalDateTime> subQuery = query.subquery(LocalDateTime.class);
Root<IncomingSwift> sq = subQuery.from(IncomingSwift.class);
subQuery.select(criteriaBuilder.greatest(sq.get(createTimestamp)))
.where(criteriaBuilder.equal(sq.get(sender), root.get(sender)));
predicateList.add(criteriaBuilder.equal(subQuery, root.get(createTimestamp)));
return criteriaBuilder.and(predicateList.toArray(new Predicate[0]));
}
}
При этом, это поля из модели, сгенерированные maven-плагином:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>${hibernate.version}</version>
</dependency>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
</configuration>
</plugin>
Выборка записей с максимальной датой
На SQL выражение выглядит так (записи с максимальным create_timestamp):
select
*
from
incoming_swift oq
where
(
select
max(sq.create_timestamp)
from
incoming_swift sq
)=oq.create_timestamp;
Если реализовать интерфейс Specification, то он будет выглядеть так:
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;
public class SwiftSpecification implements Specification<IncomingSwift> {
private final GetSwiftRequestDto dto;
public SwiftSpecification(GetSwiftRequestDto dto) {
this.dto = dto;
}
@Override
public Predicate toPredicate(Root<IncomingSwift> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicateList = new ArrayList<>();
Subquery<LocalDateTime> subQuery = query.subquery(LocalDateTime.class);
Root<IncomingSwift> subRoot = subQuery.from(IncomingSwift.class);
subQuery.select(criteriaBuilder.greatest(subRoot.get(createTimestamp)));
predicateList.add(criteriaBuilder.equal(root.get(createTimestamp), subQuery));
return criteriaBuilder.and(predicateList.toArray(new Predicate[0]));
}
}
Выборка записей с полем, значения которого входят в список значений
По аналогии с предыдущими примерами:
predicateList.add(root.get(type).in(dto.getTypes()));
Выборка записей с полем, значение которого равно указанному значению
По аналогии с предыдущими примерами:
predicateList.add(criteriaBuilder.equal(root.get(id), dto.getId()));
Выборка записей с полем, значение даты которого равно или более указанной даты
predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get(Activity_.createdDate).as(LocalDateTime.class), dto.getCreatedDateFrom()));
Case insensitive like
predicateList.add(criteriaBuilder.like(criteriaBuilder.lower(root.get(Activity_.userName)), "%" + dto.getUserName().trim().toLowerCase() + "%"));
(Просмотрено 306 раз, 1 раз за сегодня)