Java 其他实体上的Spring分页排序';s的可空属性

Java 其他实体上的Spring分页排序';s的可空属性,java,spring,spring-boot,jpa,pageable,Java,Spring,Spring Boot,Jpa,Pageable,我遇到了以下问题。。。我有三个实体: @Entity class Contract { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @ManyToOne private Employee employee; } @Entity class Employee { @Id @GeneratedValue(strategy = Gen

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

@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));
            }
        };
    }
Page getContracts(整数employeeId,可分页){
返回contractRepository.findAll(createSpecification(employeeId),可分页);
}
规范createSpecification(整数employeeId){
返回规范。其中(equalEmployeeId(employeeId));
}
规范equalEmployeeId(整数employeeId){
返回(根、criteriaQuery、criteriaBuilder)->{
if(Objects.nonNull(employeeId)){
Join joinParent=root.Join(“员工”);
返回criteriaBuilder.equal(joinParent.get(“id”)、employeeId);
}否则{
返回criteriaBuilder.isTrue(criteriaBuilder.literal(true));
}
};
}
现在,我的应用程序提供了按
部门
名称对
合同
实体进行排序的可能性,因此出现了
可分页
对象,该对象的
排序
参数设置为
employee.Department.name
。当
Employee
对象的
department
参数设置为null时,就会出现问题。。。例如,如果所有
Employee
对象的
department
参数设置为null,则返回空集合。无论员工的部门是否为空,如何更改此行为以返回所有
合同
实体

我已经尝试过不同的方法:将fetch连接添加到规范中,将
spring.jpa.properties.hibernate.order\u默认设置为null\u排序
last
,但没有任何帮助

提前感谢您的帮助


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

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

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

如果
部门
为空,则基于要返回所有
合同
实体的内容对部门

类似

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());
        }
    };
}
规范equalEmployeeId(整数employeeId){
返回(根、criteriaQuery、criteriaBuilder)->{
Join joinParent=root.Join(“员工”);
if(Objects.nonNull(employeeId)){
返回criteriaBuilder.equal(joinParent.get(“id”)、employeeId);
}否则{
返回criteriaBuilder.isTrue(joinParent.get(“department”).isNull();
}
};
}

你知道什么有用吗?正在将Spring引导更新到2.5.0。。。现在它可以正常工作了。。。(谢谢@tremendous7给我灵感!)
然而,我想@jonathan johx提供的答案可能适用于较旧的版本…

您对employee.department使用哪种联接?你已经试过左键了吗?如果您没有“手动”加入,您应该在employee.department.name上进行排序时手动添加左加入,并且您不想筛选出没有部门的员工是的,我已经尝试过了,不幸的是没有成功。我怀疑的是,如果department为null,获取department.name时会出现问题……您能提供生成的SQL语句吗?您使用的是什么版本的hibernate?是否介于5.4.4和5.4.8之间?如果是的话,这个问题可能真的很奇怪。我用您的数据模型和mysql实现了简单的测试。甚至对于没有部门的员工,我也得到了结果。下面是生成hibernate的sql。