Spring 对其他实体的可空属性进行可分页排序

Spring pageable sort on other entity's nullable attribute

我遇到了以下问题...我有三个实体:

@Entity
class Contract {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    private Employee employee;
}

@Entity
class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    private Department department;
}

@Entity
class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;
}

以及使用规范获取有关合同信息的方法:

Page<Contract> getContracts(Integer employeeId, Pageable pageable) {
    return contractRepository.findAll(createSpecification(employeeId), pageable);
}

Specification<Contract> createSpecification(Integer employeeId) {
    return Specification.where(equalEmployeeId(employeeId));
}

Specification<Contract> equalEmployeeId(Integer employeeId) {
        return (root, criteriaQuery, criteriaBuilder) -> {
            if (Objects.nonNull(employeeId)) {
                Join<Contract, Employee> joinParent = root.join("employee");
                return criteriaBuilder.equal(joinParent.get("id"), employeeId);
            } else {
                return criteriaBuilder.isTrue(criteriaBuilder.literal(true));
            }
        };
    }

现在,我的应用程序提供了按 Department 名称对 Contract 实体进行排序的可能性,因此 Pageable 对象的 sort 参数设置为 employee.department.name.当 Employee 对象将 department 参数设置为空时就会出现问题...例如,如果所有 Employee 对象都将 department 参数设置为空,则返回空集合.我该怎么做才能更改此行为以返回所有 Contract 实体,而不管 Employee's department 是否为空?

我已经尝试过不同的方法:将 fetch join 添加到规范中,将 spring.jpa.properties.hibernate.order_by.default_null_ordering 设置为 last,但没有任何帮助。

提前感谢您的帮助!

PS:请不要建议我去掉规范等——我提供的代码是为了可读性而简化的。实际上,还有更多的属性,使用 Specifications 进行过滤是最方便的方法。

您需要实现左连接以获取空内容:

Join<Contract, Employee> joinParent = root.join("employee",JoinType.LEFT);

部门也一样

如果 Department 为空,则根据您的需要 return 所有 Contract 个实体。

Specification<Contract> equalEmployeeId(Integer employeeId) {
    return (root, criteriaQuery, criteriaBuilder) -> {
        Join<Contract, Employee> joinParent = root.join("employee");
        if (Objects.nonNull(employeeId)) {
            return criteriaBuilder.equal(joinParent.get("id"), employeeId);
        } else {
            return criteriaBuilder.isTrue(joinParent.get("department").isNull());
        }
    };
}

你知道有什么帮助吗?正在将 Spring 引导更新到 2.5.0... 现在它按预期工作...(感谢 @tremendous7 的启发!) 但是,我想@jonathan-johx 提供的答案可能适用于旧版本...