我有一个通过外部REST服务检索到的对象列表,我想使用Pageable.Sort属性中的用户定义值对这些对象进行排序。
这是我的DTO对象:
@Data
@Builder
public class UserDto {
private String guid;
private String firstName;
private String lastName;
}
给定一个UserDto列表和一个Pageable.Sort,我尝试为每个定义的属性及其方向对列表进行排序。
public Page<UserDto> listToPage(List<UserDto> list, Pageable pageable) {
var sorts = pageable.getSort();
//Retrieves the name of all object fields
var fields = Arrays.stream(UserDto.class.getDeclaredFields())
.map(Field::getName)
.collect(Collectors.toList());
//For each sort specified in the pageable I need to sort the list of objects
for (var sort : sorts) {
//If a given property does not exist. Throws an exception.
if (!fields.contains(sort.getProperty()))
throw new InvalidDataException("Property [" + sort.getProperty() + "] does not exists in " + UserDto.class.getName() + " class");
//Looks for the property and its direction
switch (sort.getProperty()) {
case "guid":
list = sort.getDirection().isDescending() ?
list.stream().sorted(Comparator.comparing(UserDto::getGuid).reversed()).collect(Collectors.toList()) :
list.stream().sorted(Comparator.comparing(UserDto::getGuid)).collect(Collectors.toList());
break;
case "firstName":
list = sort.getDirection().isDescending() ?
list.stream().sorted(Comparator.comparing(UserDto::getFirstName).reversed()).collect(Collectors.toList()) :
list.stream().sorted(Comparator.comparing(UserDto::getFirstName)).collect(Collectors.toList());
break;
case "lastName":
list = sort.getDirection().isDescending() ?
list.stream().sorted(Comparator.comparing(UserDto::getLastName).reversed()).collect(Collectors.toList()) :
list.stream().sorted(Comparator.comparing(UserDto::getLastName)).collect(Collectors.toList());
break;
default:
break;
}
}
final int start = (int) pageable.getOffset();
final int end = Math.min((start + pageable.getPageSize()), list.size());
var subList = list.subList(start, end);
return new PageImpl<>(subList, pageable, list.size());
}
除了传递多个属性来对用户列表进行排序外,所有这些都可以正常工作。
第一轮应该按firstName:ASC排序,然后在第二轮中,应该按lastName:DESC排序,记住第一个排序顺序,但这不是这样做的。
有没有什么方法可以处理同一个列表在不同轮中的多个排序?我不想使用thenComparing操作符,因为我想通过用户交互动态地完成这一操作。
未来方法是以一种通用的方式创建此函数,以处理任何对象并对其属性进行排序,从而利用此JPA提供的类。
这是我的测试案例:
@Test
void testCase1() {
var userDtoList = List.of(
UserDto.builder().firstName("A3").lastName("B7").guid("G000a").build(),
UserDto.builder().firstName("A2").lastName("B4").guid("G000b").build(),
UserDto.builder().firstName("A3").lastName("B1").guid("G000c").build(),
UserDto.builder().firstName("A2").lastName("B5").guid("G000d").build(),
UserDto.builder().firstName("A1").lastName("B6").guid("G000e").build(),
UserDto.builder().firstName("A2").lastName("B3").guid("G000f").build(),
UserDto.builder().firstName("A1").lastName("B2").guid("G000g").build()
);
Sort firstNameSort = Sort.by("firstName");
Sort lastNameSort = Sort.by("lastName").descending();
Sort sort = firstNameSort.and(lastNameSort);
var pageable = PageRequest.of(0, 5, sort);
var result = userService.listToPage(userDtoList, pageable);
result.getContent().forEach(System.out::println);
assertEquals(5, result.getContent().size());
}
2条答案
按热度按时间vfhzx4xs1#
如果您希望从数据库中检索用户,您可以使用Spring Data ,如下所示:
f4t66c6m2#
对于面临同样问题的人,我使用Java反射创建了一个通用的PageUtils类来解决这个问题。
您可以在下面的Github repo中找到代码:
https://github.com/rortegat/generic-pageable