当前位置: 首页 > 知识库问答 >
问题:

可分页+@query+JOIN(fetch?)在Spring数据不起作用

卞安邦
2023-03-14

我试图通过使用Spring Data中的@query注释,将排序与pageable集成在联接字段上。

Caused by: org.hibernate.QueryException: could not resolve property: name of: (....).model.employee.Employee
  • 有人建议将countQuery添加到@query参数中,以便在某种程度上与分页(spring data jpa@query和pagable)
  • 相对应
  • 我已经学习了Baeldung的教程,但这不包括联接
  • Spring-Data FETCH JOIN与分页不起作用也建议使用CountQuery,但我更喜欢使用page ,而不是list .

我将在下面留下一些代码示例。如果我遗漏了一些重要的东西,请随时询问更新。

// 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控制器的方法之一:

@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();
    }
}

共有1个答案

仲浩旷
2023-03-14

尝试下面的代码。

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表的外键。

 类似资料:
  • 问题内容: 我正在尝试使用HQL使用JOIN FETCH来获取我的实体以及子实体,如果我想要所有结果,这可以正常工作,但是如果我想要一个Page,则不是这样 我的实体是 并且由于我有数百万次的访问,因此我需要使用Pageable,并且希望在单个数据库查询中提取注释: 该HQL调用引发以下异常: 一旦我删除分页,一切正常 显然问题是来自Spring-Data的count查询,但是我们如何解决呢? 问

  • 我正在尝试使用HQL来获取我的实体以及使用JOIN FETCH的子实体,如果我想要所有的结果,这很好工作,但如果我想要一个页面,情况就不是这样了 我的实体是 因为我有数百万次的访问,所以我需要使用Pageable,并且我希望在单个数据库查询中获取注释,比如: 该HQL调用引发以下异常:

  • 我使用的是spring-data-jpa。我写了一个本机查询,但它不起作用。这是我的实体类: 以下是查询: 起初,当我没有编写nativeQuery=true时,应用程序没有构建,我得到了一个异常“加入jpa的预期路径”。当我设置nativeQuery=true时,应用程序已启动,但当我调用该函数时,我收到以下错误: 是否有任何其他设置或注释可以解决此问题?我在谷歌上搜索过,但在所有情况下都有两个

  • 我对hibernate和spring-data-jpa还很陌生。我想做的就是使用分页(大约有4000万条记录)来获取一个实体和它的所有相关实体。也就是说,一个查询来急切地获取根实体和它们的所有映射实体/集合=1个查询 我有2个实体类(Customer和Order)如下: 客户实体 尝试使用batchSize,但由于某种原因它无法工作(同样的N+1问题)。 //@Fetch(FetchMode.Se

  • 我在哪里出错了?如果我试图添加可分页对象来查询并运行代码,我将得到以下错误: 无法使用请求的结果类型[java.lang.long]为具有多个返回的查询创建TypedQuery;嵌套异常是java.lang.IllegalArgumentException:无法使用请求的结果类型[java.lang.long]为具有多个返回的查询创建TypedQuery

  • 问题内容: 我有实体 与实体有关 与实体有关 在实体中,我有用注释的字段。我也有仓库 当我称它为 例外时 如何忽略从数据库加载该字段? 问题答案: 我找到了解决方案,问题出在“注释”中,当我将其更改为正常时。