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 提供的答案可能适用于旧版本...
我遇到了以下问题...我有三个实体:
@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 提供的答案可能适用于旧版本...