java - 当实体具有多对多关系时如何使用条件查询?

标签 java spring-boot criteria-api

我有 2 个表(人员和技能);它们之间是多对多的关系。

这来自 person 实体:

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@JoinTable(name = "person_skill",
        joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "skill_id", referencedColumnName = "id"))
private Set<Skill> skills;

这来自技能:

 @JsonBackReference
@ManyToMany(mappedBy = "skills")
private Set<Person> persons;

我尝试执行一个查询,您可以通过许多参数找到一个人,但所有参数都应该是可选的。所以我创建了一些规​​范:

 public static Specification<Person> firstNameContains(String firstName) {
    return (person, cq, cb) -> cb.like(person.get("firstName"), "%" + firstName + "%");
}

public static Specification<Person> isStudent(Boolean isStudent) {
    return (person, cq, cb) -> cb.equal(person.get("isStudent"), isStudent);
}

我在服务中创建了这个函数:

 @Override
public Page<Person> findByParams(Long id,
                                 String firstName,
                                 String lastName,
                                 Boolean isStudent,
                                 Boolean isActive,
                                 String email,
                                 String phone,
                                 Set<Long> skills,
                                 Pageable pageable) {
    List<Specification> specifications = new ArrayList<>();
    if(firstName != null){
        specifications.add(PersonSpecifications.firstNameContains(firstName));
    }
    if (isStudent != null){
        specifications.add(PersonSpecifications.isStudent(isStudent));
    }
    if (skills != null){
        specifications.add(PersonSpecifications.hasSkills(skills));
    }
    Optional<Specification> spec = specifications.stream().reduce((s, acc) -> acc.and(s));
    if(spec.isPresent()) {
        return personRepository.findAll(spec.get(), pageable);
    }
    return personRepository.findAll(pageable);
}

由 Controller 中的此函数调用:

    @GetMapping(FIND)
Page<Person> findByParams(@RequestParam(value = "id", required = false) Long id,
                          @RequestParam(value = "firstName", required = false) String firstName,
                          @RequestParam(value = "lastName", required = false) String lastName,
                          @RequestParam(value = "isStudent", required = false) Boolean isStudent,
                          @RequestParam(value = "isActive", required = false) Boolean isActive,
                          @RequestParam(value = "email", required = false) String email,
                          @RequestParam(value = "phone", required = false) String phone,
                          @RequestParam(value = "skills", required = false) Set<Long> skills,
                          Pageable pageable) {
    return personService.findByParams(id, firstName, lastName, isStudent, isActive, email, phone, skills, pageable);
}

我的问题是 hasSkills 规范应该是什么样子才能发挥作用。

最佳答案

您可以在规范中使用连接。

person.join("skills").("id").in(skills);

这里id将是技能类别中的主键属性名称。

关于java - 当实体具有多对多关系时如何使用条件查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57745546/

相关文章:

java - 在 JOOQ 分页之前获取总行数?

spring-boot - Spring Boot JSON 返回无限嵌套对象

java - 将代理数据设置为 Spring SOAP Web 服务模板

java - 是否可以通过 JPA 和 CriteriaBuilder 的复合键进行排序

java - 使用 NumberLong 在 mongodb 中创建查询时出现问题

java - hibernate : for a single table group attributes into a subclass

java - 线程缺少其他线程的更新

java - 如何在 JUnit 中重用方法和测试?

spring - 使用 Spring Boot + IntelliJ 进行开发的最佳方式

java - 条件生成器分组依据和计数不起作用