I have a table that looks kinda like this
Entity Name | Year | Person Name |
---|---|---|
School 1 | 2021 | Person 1 |
School 1 | 2021 | Person 2 |
School 1 | 2020 | Person 1 |
School 2 | 2021 | Person 1 |
I want to be able to use Spring JPA to return only one result per Entity Name. For example, the results would be School 1, School 2. I don't care which School 1 row is retrieved, I just need to only retrieve one. I need to be able to use a Specification, return Pagination results, and sort the results.
Here is what I have tried so far
Repository
@Repository
public interface Repository extends JpaRepository<Model, UUID>,
JpaSpecificationExecutor<Model>{
}
Service
repository.findAll(Specification
.searchByDtoSpec(searchDto), page)
.map(this::mapToDto);
Specification
public static Specification<Model> searchByDtoSpec(
final SearchDto searchDto) {
return (root, query, cb) -> {
final List<Predicate> predicates = new ArrayList<>();
query.multiselect(root.get("entityName"),root.get("personName")).distinct(true);
return cb.and(predicates.toArray(Predicate[]::new));
};
}
To answer my own question, I was not able to find a way without using CriteriaBuilder and CriteriaQuery. I had to combine a CriteriaQuery multiselect and a CriteriaQuery distinct Here is a snippet of my code to help anyone else in my situation:
public Page<Model> findAllByFilters(final Pageable page,
final SearchDto searchDto) {
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Model> cq = cb.createQuery(Model.class);
final Root<Model> root = cq.from(Model.class);
final List<Predicate> predicates = getCustomPredicates(root, cq, cb, searchDto,
currentDate, false);
cq.where(predicates.toArray(Predicate[]::new));
cq.multiselect(root.get("entityName"), root.get("year"), root.get("personName");
cq.distinct(true);
final TypedQuery<Model> tq = em.createQuery(cq);
// Code for Pagination
...
final List<Model> list = tq.getResultList();
return new PageImpl<Model>(list, page, count);
}
In your Repository
interface add a method like this
Model findFirstByOrderByPersonNameAsc();
You can order it however you want. You can also return an optional Optional<Model>
if you would like.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.