簡體   English   中英

Pageable + @Query + JOIN (fetch?) in Spring 數據不起作用

[英]Pageable + @Query + JOIN (fetch?) in Spring Data don't work

我正在嘗試使用來自 Spring 數據的@Query注釋在連接字段上將排序與Pageable集成。

第一個接口的方法(沒有@Query但有Pageable )就像一個魅力。 就像當我只使用@Query獲取一個 Employee 但不是Pageable我在那里使用Optional<Employee> (第三種方法)時一樣。 但是,當我嘗試將這兩者合而為一時,樂趣就開始了——它不再起作用了。

當我嘗試按name字段對數據進行排序時,它會出現以下錯誤:

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

所以問題是:如何告訴 spring 在連接字段中查找name 如何使用 Spring 數據執行此操作?

我已經嘗試了幾件事,但它們沒有用,或者我仍然不知道如何正確使用它們:

我將在下面留下一些代碼示例。 如果我遺漏了一些重要的東西,請隨時要求更新。

// Employee
@Entity
@Table(name = "employee", schema = "emp")
@Data
@NoArgsConstructor
public class Employee {
    private static final String SEQUENCE = "EMPLOYEE_SEQUENCE";

    @Id
    @SequenceGenerator(sequenceName = SEQUENCE, name = SEQUENCE, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
    private Long id;

    @Column(name = "employee_number")
    private String employeeNumber;

    @Column
    @Enumerated(EnumType.STRING)
    private EmployeeStatus status;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
    @JoinColumn(name = "id_details")
    private Details details;

    // some other fields ...
}
// Details
@Entity
@Table(name = "details", schema = "emp")
@Data
@NoArgsConstructor
public class Details {
    private static final String SEQUENCE = "DETAILS_SEQUENCE";

    @Id
    @SequenceGenerator(sequenceName = SEQUENCE, name = SEQUENCE, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
    private Long id;

    private String name;

    private String surname;

    // some other fields ...
}
// EmployeeDTO
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder(toBuilder = true)
public class EmployeeDTO {
    private Long id;
    private String employeeNumber;
    private String status;
    private String name;
    private String surname;

    // some other fields ...
}
// EmployeeRepository
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

    // 1st method
    Page<Employee> findByStatus(EmployeeStatus status, Pageable pageable);

    // 2nd method
    @Query(value = "select e from Employee e join e.details where e.status = :status",
            countQuery = "select count(*) from Employee e join e.details where e.status = :status")
    Page<Employee> getEmployeeDetails(@Param("status") EmployeeStatus status, Pageable pageable);

    // 3rd method
    @Query("select e from Employee e join fetch e.details where e.id = :id")
    Optional<Employee> findByIdWithDetails(Long id);

    // ...
}
// EmployeeService
@Service
public class EmployeeService {

    private final EmployeeRepository employeeRepository;
    private final EntityDtoConverter entityDtoConverter;

    @Autowired
    public EmployeeService(EmployeeRepository employeeRepository, EntityDtoConverter entityDtoConverter) {
        this.employeeRepository = employeeRepository;
        this.entityDtoConverter = entityDtoConverter;
    }

    public EmployeeResponse getEmployeesByStatus(EmployeeStatus status, int pageSize, int pageIndex, Sort.Direction sortDirection, String sortColumn) {
        Page<EmployeeDTO> employeePage = employeeRepository.findByStatus(status, PageRequest.of(pageIndex, pageSize, Sort.by(sortDirection, sortColumn)))
                .map(entityDtoConverter::convertEmployeeBaseToDto);
        return new EmployeeResponse(employeePage);
    }

    public EmployeeResponse getEmployeeDetails(EmployeeStatus status, int pageSize, int pageIndex, Sort.Direction sortDirection, String sortColumn) {
        Page<EmployeeDTO> employeePage = employeeRepository.getEmployeeDetails(status, PageRequest.of(pageIndex, pageSize, Sort.by(sortDirection, sortColumn)))
                .map(entityDtoConverter::convertToEmployeeWithDetailsDto);
        return new EmployeeResponse(employeePage);
    }

    // ...
}
// EntityDtoConverter
@Component
public class EntityDtoConverter {

    public EmployeeDTO convertEmployeeBaseToDto(Employee entity) {
        return EmployeeDTO.builder()
                .id(entity.getId())
                .employeeNumber(entity.getEmployeeNumber())
                .status(entity.getStatus())
                .build();
    }

    public EmployeeDTO convertToEmployeeWithDetailsDto(Employee entity) {
        return convertEmployeeBaseToDto(entity).toBuilder()
                .name(entity.getDetails().getName())
                .surname(entity.getDetails().getSurname())
                .build();
    }

    // ...
}

編輯:

這是我的rest controller的方法之一:

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

試試下面的代碼。

Specification<Employee> joins = (employee, query, cb) ->  {
            Join<Employee, Detail> details = employee.join("details");

            return cb.and(
                    employee.equal(employee.get("name", name)),
                    details.equal(details.get("name", detailName))
            );
        };

        PageRequest pageRequest = new PageRequest(0, 2, new Sort(Sort.Direction.DESC, "name"));

        Page<Employee> customerPage = employeeRepository.findAll(joins, pageRequest);

這里我們試圖通知 JPA 這個名字是 Employee 表的外鍵。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM