简体   繁体   中英

In back end (java spring boot) sorting, how to sort with Alias name using pageable? Without parent table as prefix

I am using backend pagination and sorting with java spring boot pageable . While passing sort field as usercount (This gives count of user_role_mapping ), Java triggering an error column f.usercount does not exist . Actually usercount not a column it's an Alias name.

How to sort using usercount as Alies name without f. as prefix?

API URL:

http://localhost:8080/facility/list?pageNumber=0&pageSize=10&sortBy=usercount&sortType=asc

Default sortBy & sortType are id and desc respectively in controller layer.

Java Code give below:

Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).descending());
if (sortType.equalsIgnoreCase("asc")) {
    pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).ascending());
}
Page<FacilityProjection> facilityList = facilityRepository.facilityListing(12,pageable);

Postgres sql Hibernate query for listing facility details along with user count based on role id, given below:

@Query(nativeQuery = true, value = " Select f.name as facilityname,f.id as facilityid,count(urm.id) as usercount 
 from facility f
 join user u on f.user_id=u.id 
 join user_role_mapping urm on u.id = urm.user_id 
 where urm.role_id=:roleId ")
Page<FacilityProjection> facilityListing(@Param("roleId") Long roleId,Pageable pageable);

The problem is that usercount is aggregation function result. To order by this field query have to contain order by count(urm.id) instead of order by usercount .

In this case I'd suggest you to resort page content using Collections::sort

boolean sortByUserCount = sortBy.equalsIgnoreCase("usercount");
boolean desc = sortType.equalsIgnoreCase("desc");

final Pageable pageable;

if (sortByUserCount) {
    pageable = PageRequest.of(pageNumber, pageSize);
} else {
    if (desc) {
        pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).descending());
    } else {
        pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).ascending());
    }
}

Page<FacilityProjection> facilityList = facilityRepository.facilityListing(12, pageable);

if (sortByUserCount) {
    Comparator<FacilityProjection> comparator = Comparator.comparing(FacilityProjection::getUserCount);

    if(desc) {
        comparator = comparator.reversed(); 
    }
    Collections.sort(facilityList.getContent(), comparator);
}

As far as I know, this is not possible.

Having said that, I think this is a perfect use case forBlaze-Persistence Entity Views .

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:

@EntityView(Facility.class)
public interface FacilityProjection {
    @IdMapping
    Long getId();
    String getName();
    @Mapping("SIZE(users)")
    Long getUsercount();
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

FacilityProjection a = entityViewManager.find(entityManager, FacilityProjection.class, id);

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features so you can see this as a replacement for Spring Data Projections that supports more use cases!

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM