基于实体中集合大小的java顺序结果集

5gfr0r5j  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(392)

考虑下面的实体-

class Team {
    private String name;

    @OneToMany
    private Set<Employee> employees;
}

class Employee {
    private String name;

    @OneToMany
    private Set<Skill> skills;
}

class Skill {
    private String name;
    private boolean active;
    private Date expiryDate;
}

我需要对团队结果集进行排序,使具有最大活动和未过期技能的团队排在第一位。我使用springboot规范和criteriaquery来过滤不同领域的团队。到目前为止,我有下面的代码,这不是预期的工作。

public class TeamSpecs implements Specification<Team> {

  @Override
  public Predicate toPredicate(Root<Team> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

    Order o = cb.desc(cb.sum(cb.size(root.join("employees").get("skills")));
    cq.orderBy(o));

    return cb.like(cb.equal(root.get("name"), "%" + value + "%"));
  }
}

我有什么遗漏吗?请建议

cwxwcias

cwxwcias1#

要做到这一点,首先必须联接表,然后过滤条目,将它们分组,然后对它们进行排序。
因此,您的sql查询应该如下所示:

select team.*
from Team team
  inner join employee
  inner join skill
where skill.active = true and skill.expiryDate > today
group by team.name
order by count(skill.name) desc

旁注:
使用 Specification 在这种情况下,这不是您想要做的,因为它们不代表完整的查询,而是在多个查询中使用的语句或查询的一部分。
使用jpa criteriaquery:

public List<Team> getTeamsWithActiveSkills() {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Team> cq = cb.createQuery(Team.class);
        Root<Team> root = cq.from(Team.class);
        Join<Team, Employee> employees = root.join("employees");
        Join<Team, Skill> skills = employees.join("skills");

        Predicate isActive = cb.isTrue(skills.get("active"));
        Predicate isNonExpired = cb.greaterThan(skills.get("expiryDate"), LocalDate.now());

        cq.where(isActive, isNonExpired).groupBy(root.get("name"));

        Order order = cb.desc(cb.count(skills));
        cq.orderBy(order);

        return em.createQuery(cq).getResultList();
    }

因为我个人觉得criteriaquery很难阅读,而且不直观,所以可以使用querydsl作为替代方法。
使用querydsl:

public List<Team> getTeamsWithActiveSkills() {

        QTeam team = QTeam.team;
        QEmployee employee = QEmployee.employee;
        QSkill skill = QSkill.skill;
        JPQLQuery<Team> query = from(team).join(team.employees, employee).join(employee.skills, skill);

        query = teamJPQLQuery.where(skill.active.isTrue().and(skill.expiryDate.gt(LocalDate.now())));

        query = query .groupBy(team.name);
        query = query .orderBy(skill.name.count().desc());

        return query.fetch();
    }

相关问题