【问题标题】:Spring pageable sort on other entity's nullable attribute对其他实体的可为空属性进行 Spring 可分页排序
【发布时间】:2021-08-08 09:12:58
【问题描述】:

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

@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 参数设置为null 时就会出现问题...例如,如果所有Employee 对象都将department 参数设置为null,则返回空集合。无论Employee's department 是否为空,我可以做些什么来改变这种行为以返回所有Contract 实体?

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

提前感谢您的帮助!

PS:请不要建议我摆脱规范等 - 为了便于阅读,我提供的代码已被简化。实际上,还有更多的属性,使用规范进行过滤是最方便的方法。

【问题讨论】:

  • 您对employee.department 使用什么样的join?你已经尝试左加入了吗?如果您没有“手动”加入它,您应该在对employee.department.name 进行排序并且您不想过滤掉没有部门的员工时手动添加左加入
  • 是的,我已经试过了,可惜没有成功。我怀疑如果部门为空,获取部门名称存在问题......
  • 能否提供生成的SQL语句?
  • 你使用的是什么版本的休眠?它在 5.4.4 和 5.4.8 之间吗?如果是问题可能是这个hibernate.atlassian.net/browse/HHH-13670
  • 这真的很奇怪。我用你的数据模型和 mysql 实现了简单的测试。即使对于没有部门的员工,我也能得到结果。这是生成休眠的sql。

标签: java spring spring-boot jpa pageable


【解决方案1】:

你需要实现左连接来获取空内容:

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

部门也一样

【讨论】:

    【解决方案2】:

    如果Department 为空,则根据您想要返回的所有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());
            }
        };
    }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2010-11-29
        • 1970-01-01
        • 1970-01-01
        • 2020-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多