pageable+@query+join(fetch?)不起作用

7y4bm7vi  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(277)

我想把分类和 Pageable 关于使用 @Query 来自Spring Data 的注解。
第一个接口的方法(没有 @Query 但是有了 Pageable )很有魅力。就像我只招一个员工 @Query 但不是 Pageable 我在用 Optional<Employee> 有(第三种方法)。但是当我试着把这两个放在一起的时候,乐趣就开始了——它不再起作用了。
当我试图按 name 它尖叫着说这个错误:

  1. Caused by: org.hibernate.QueryException: could not resolve property: name of: (....).model.employee.Employee

所以问题是:如何告诉spring去寻找 name 在关联字段中?如何处理spring数据?
我已经试过几种方法,但都不起作用,或者我仍然不知道如何正确使用它们:
有人建议添加 countQuery@Query 参数,因此这在某种程度上与分页(spring data jpa@query和pageable)相对应
我遵循了baeldung的教程,但这不包括连接
带分页的spring数据获取连接不起作用也建议使用 countQuery 但我更愿意坚持 Page<Employee> 而不是 List<Employee> .
我将在下面留下一些代码示例。如果我遗漏了一些重要的事情,请随时要求更新。

  1. // Employee
  2. @Entity
  3. @Table(name = "employee", schema = "emp")
  4. @Data
  5. @NoArgsConstructor
  6. public class Employee {
  7. private static final String SEQUENCE = "EMPLOYEE_SEQUENCE";
  8. @Id
  9. @SequenceGenerator(sequenceName = SEQUENCE, name = SEQUENCE, allocationSize = 1)
  10. @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
  11. private Long id;
  12. @Column(name = "employee_number")
  13. private String employeeNumber;
  14. @Column
  15. @Enumerated(EnumType.STRING)
  16. private EmployeeStatus status;
  17. @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  18. @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
  19. @JoinColumn(name = "id_details")
  20. private Details details;
  21. // some other fields ...
  22. }
  1. // Details
  2. @Entity
  3. @Table(name = "details", schema = "emp")
  4. @Data
  5. @NoArgsConstructor
  6. public class Details {
  7. private static final String SEQUENCE = "DETAILS_SEQUENCE";
  8. @Id
  9. @SequenceGenerator(sequenceName = SEQUENCE, name = SEQUENCE, allocationSize = 1)
  10. @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
  11. private Long id;
  12. private String name;
  13. private String surname;
  14. // some other fields ...
  15. }
  1. // EmployeeDTO
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. @Data
  5. @Builder(toBuilder = true)
  6. public class EmployeeDTO {
  7. private Long id;
  8. private String employeeNumber;
  9. private String status;
  10. private String name;
  11. private String surname;
  12. // some other fields ...
  13. }
  1. // EmployeeRepository
  2. @Repository
  3. public interface EmployeeRepository extends JpaRepository<Employee, Long> {
  4. // 1st method
  5. Page<Employee> findByStatus(EmployeeStatus status, Pageable pageable);
  6. // 2nd method
  7. @Query(value = "select e from Employee e join e.details where e.status = :status",
  8. countQuery = "select count(*) from Employee e join e.details where e.status = :status")
  9. Page<Employee> getEmployeeDetails(@Param("status") EmployeeStatus status, Pageable pageable);
  10. // 3rd method
  11. @Query("select e from Employee e join fetch e.details where e.id = :id")
  12. Optional<Employee> findByIdWithDetails(Long id);
  13. // ...
  14. }
  1. // EmployeeService
  2. @Service
  3. public class EmployeeService {
  4. private final EmployeeRepository employeeRepository;
  5. private final EntityDtoConverter entityDtoConverter;
  6. @Autowired
  7. public EmployeeService(EmployeeRepository employeeRepository, EntityDtoConverter entityDtoConverter) {
  8. this.employeeRepository = employeeRepository;
  9. this.entityDtoConverter = entityDtoConverter;
  10. }
  11. public EmployeeResponse getEmployeesByStatus(EmployeeStatus status, int pageSize, int pageIndex, Sort.Direction sortDirection, String sortColumn) {
  12. Page<EmployeeDTO> employeePage = employeeRepository.findByStatus(status, PageRequest.of(pageIndex, pageSize, Sort.by(sortDirection, sortColumn)))
  13. .map(entityDtoConverter::convertEmployeeBaseToDto);
  14. return new EmployeeResponse(employeePage);
  15. }
  16. public EmployeeResponse getEmployeeDetails(EmployeeStatus status, int pageSize, int pageIndex, Sort.Direction sortDirection, String sortColumn) {
  17. Page<EmployeeDTO> employeePage = employeeRepository.getEmployeeDetails(status, PageRequest.of(pageIndex, pageSize, Sort.by(sortDirection, sortColumn)))
  18. .map(entityDtoConverter::convertToEmployeeWithDetailsDto);
  19. return new EmployeeResponse(employeePage);
  20. }
  21. // ...
  22. }
  1. // EntityDtoConverter
  2. @Component
  3. public class EntityDtoConverter {
  4. public EmployeeDTO convertEmployeeBaseToDto(Employee entity) {
  5. return EmployeeDTO.builder()
  6. .id(entity.getId())
  7. .employeeNumber(entity.getEmployeeNumber())
  8. .status(entity.getStatus())
  9. .build();
  10. }
  11. public EmployeeDTO convertToEmployeeWithDetailsDto(Employee entity) {
  12. return convertEmployeeBaseToDto(entity).toBuilder()
  13. .name(entity.getDetails().getName())
  14. .surname(entity.getDetails().getSurname())
  15. .build();
  16. }
  17. // ...
  18. }

编辑:

这是我的rest控制器的方法之一:

  1. @GetMapping
  2. public ResponseEntity<EmployeeResponse> getEmployeesByStatus(EmployeeStatus status, int pageSize, int pageIndex, String sortDirection, String sortColumn) {
  3. try {
  4. EmployeeResponse employeeResponse = employeeService.getEmployeesByStatus(status, pageSize, pageIndex, Sort.Direction.fromString(sortDirection), sortColumn);
  5. return employeeResponse.getTotalElements().equals(0L) ? ResponseEntity.noContent().build() : ResponseEntity.ok(employeeResponse);
  6. } catch (Exception e) {
  7. log.error(ERROR_MESSAGE, e);
  8. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  9. }
  10. }
ifmq2ha2

ifmq2ha21#

试试下面的代码。

  1. Specification<Employee> joins = (employee, query, cb) -> {
  2. Join<Employee, Detail> details = employee.join("details");
  3. return cb.and(
  4. employee.equal(employee.get("name", name)),
  5. details.equal(details.get("name", detailName))
  6. );
  7. };
  8. PageRequest pageRequest = new PageRequest(0, 2, new Sort(Sort.Direction.DESC, "name"));
  9. Page<Employee> customerPage = employeeRepository.findAll(joins, pageRequest);

这里我们试图通知jpa这个名称是employee表的外键。

相关问题