java - 当实体具有多对多关系时如何使用条件查询?
问题描述
我有 2 张桌子(人员和技能);它们之间存在多对多的关系。
这是来自个人实体:
@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);
}
由控制器中的此函数调用:
@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 - 为什么在数组中查找索引不起作用
- laravel - 动态路由怎么可能
- amazon-web-services - WAF 使用包含空格和单词 ON 的 POST 数据阻止 http 请求
- sharepoint-online - SharePoint API CAML 视图:即使有行限制,当我在 CAML 中包含查询时,我也会收到列表阈值错误
- java - 即使没有与PDFBox中的布局相关的属性(文档目录结构中的/ A),也获取标签的相关BBox?
- reactjs - 反应 onClick 事件在组件中不起作用
- angular - 找不到在 Angular 8 组件中返回对象数组的方法
- powershell - 用于检索第二个模式值的 Powershell 命令
- ios - 有时会出现错误,否则工作正常,如何确保消除错误?
- java - 访问由已实现接口引用的枚举的注释