Java 如何将列表<Object>从 JPA 分页转换为页面



我的自定义搜索方法在Jpa存储库中遇到问题。我实现此方法进行自定义搜索,在此方法中,我从SQL数据库中List<Car>,并尝试将其转换为JPA分页和排序中的Page<Car>对象,但是我尝试这样做的方式不起作用。这只是分页的错觉,因为在邮递员/互联网浏览器中,我看到了列表中的所有元素,当我在端点中更改页面和大小值时,什么也没改变。

有人知道如何帮助吗?

GitHub 项目:https://github.com/s0bieskii/DemoCarRental

来自控制器的终结点:

@GetMapping("/find")
ResponseEntity<Page<CarDTO>> readAllCarsFiltered(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "5") int size,
Pageable pageable,
@RequestParam(required = false) String brand,
@RequestParam(required = false) String model,
@RequestParam(required = false) String type,
@RequestParam(required = false) Integer registrationYear,
@RequestParam(required = false) String color,
@RequestParam(required = false) String fuel,
@RequestParam(required = false) String transmission,
@RequestParam(required = false) String doors,
@RequestParam(required = false, defaultValue = "9999999999") double price) {
return ResponseEntity.ok(carService.customerSearch(pageable,
brand, model, type, registrationYear, color, fuel, transmission, doors, price));
}

我的服务:

public Page<CarDTO> customerSearch(Pageable pageable, String brand, String model, String type, Integer registrationNumber, String color,
String fuel, String transmission, String doors, double price){
return carRepository.search(pageable, brand, model, type, registrationNumber, color, fuel, transmission, doors, price)
.map(car -> carMapper.carToDto(car));
}

我从RepositoryImplementation自定义搜索方法:

@Override
public Page<Car> search(Pageable pageable, String brand, String model, String type, Integer registrationYear, String color,
String fuel, String transmission, String doors, double price) {
int var = 0;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Car> query = cb.createQuery(Car.class);
Root<Car> car = query.from(Car.class);
query.select(car);
Predicate predicate = cb.greaterThan(car.get("id"), var);
if (brand != null) predicate = cb.and(predicate, cb.equal(car.get("brand"), brand));
if (model != null) predicate = cb.and(predicate, cb.equal(car.get("model"), model));
if (type != null) predicate = cb.and(predicate, cb.equal(car.get("type"), type));
if (registrationYear != null)
predicate = cb.and(predicate, cb.equal(car.get("registrationNumber"), registrationYear));
if (color != null) predicate = cb.and(predicate, cb.equal(car.get("color"), color));
if (fuel != null) predicate = cb.and(predicate, cb.equal(car.get("fuel"), Fuel.stringToFuelEnum(fuel)));
if (transmission != null)
predicate = cb.and(predicate, cb.equal(car.get("transmission"), Transmission.stringToTransmissionEnum(transmission)));
if (doors != null) predicate = cb.and(predicate, cb.equal(car.get("doors"), doors));
if (price != 0) predicate = cb.and(predicate, cb.lessThan(car.get("price"), price));
//predicate = cb.and(predicate, cb.equal(car.get("available"), available));
List<Car> carList=entityManager.createQuery(query.where(predicate)).getResultList();
return new PageImpl<Car>(carList, pageable,carList.size());
}
}

当您执行自定义查询并希望使用 Pageable 时,由您来实现一个逻辑来为结果列表创建分页。在您的情况下,您没有这样做,所以它可能(您说它不起作用,但没有说什么不起作用,所以我只能猜测)只是返回整个结果列表而没有应用分页。

一个简单的解决方案是使用sublist并将该操作的结果用作PageImpl的参数。最大的问题是您仍然在后台从数据库中获取整个结果列表,这会产生不必要的开销。

您还可以使用

em.createQuery(query.where(predicate))
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList()

现在分页是在数据库中完成的,这要好得多。

或者,您可以省去一些麻烦并使用SpringsSpecification界面,而不是创建自己的搜索方法。

首先,您的CarRepository需要扩展JpaSpecificationExecutor。现在 spring 将为您的存储库生成一个findAll(Specification, Pageable)方法。

第二步是创建搜索规范:

public class SearchSpecification implements Specification<Car> {
private final String brand;
private final String model
private final String type
private final Integer registrationYear
private final String color
private final String fuel
private final String transmission
private final String doors
private final double price
// constructor & maybe getter
public Predicate toPredicate(Root<Car> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
// Create your search predicate
}
}

现在你可以简单地打电话给carRepository.findAll(new SearchSpecification (/* parameters */), pageable);,春天会为你做寻呼。

最新更新