我有3个表,例如alarm
,alarmTag
和alarm_alarmTag
。 alarm
和alarmTag
表具有ManyToMany关系。 alarm_alarmTag
表正在映射alarm
和alarmTag
表。
每个警报可以具有许多警报标签。例如,alarm1
具有tag1
和tag2
。因此,我想创建一个搜索过滤器,当我在该过滤器上选择tag1
时,我想显示具有tag1
的警报。
我已经用join做到了,但是问题是当我过滤tag1
时,它在标签列上仅显示tag1
,但该列上还有其他标签。
过滤前:
+------------------+
| alarm table |
+------------------+
| id | tag |
+------------------+
| 1 | tag1, tag2 |
| 2 | tag3, tag4 |
+------------------+
用
tag1
过滤后:+------------------+
| alarm table |
+------------------+
| id | tag |
+------------------+
| 1 | tag1 |(this column must also have `tag2`)
+------------------+
模型:
public class ActiveAlarm {
@Id
private Long id;
@ManyToMany(cascade = CascadeType.PERSIST)
private Set<AlarmTag> alarmTag;
}
控制器:
@GetMapping("/active")
public List<ActiveAlarmView> findAll(@RequestParam(required = false, defaultValue = "") List<Long> alarmTag) {
var data = repository.findAll(ActiveAlarmSpecification.filter(alarmTag));
return data.stream().map(record -> ActiveAlarmView.builder()
.id(record.getId())
.alarmTag(record.getAlarmTag()))
.build()).collect(Collectors.toList());
}
过滤器规格:
public class ActiveAlarmSpecification {
/**
* Filter Specification.
*/
public static Specification<ActiveAlarm> filter(List<Long> alarmTag) {
return (root, query, cb) -> {
query.distinct(true);
ArrayList<Predicate> predicates = new ArrayList<>();
if (!alarmTag.isEmpty()) {
//***problem is in this line***
predicates.add(root.join("alarmTag").get("id").in(alarmTag));
}
return cb.and(predicates.toArray(new Predicate[0]));
};
}
}
alarmTag型号:
public class AlarmTag {
@Id
private Long id;
private String label;
}
这是我的请求链接:
http://localhost:8080/api/test/v1/alarm/active?alarmTag=1
最佳答案
您将不得不分别获取它们或使用group by
来汇总标签名称/标识(不幸的是,使用DTO进行投影)。
这背后的原因就是SQL会产生什么。查询将为+-,例如:
SELECT * FROM alarm a JOIN alarm_tag at ON ... JOIN tag t ON ... WHERE t.id IN (your,tags)
当您只有单个标签时,此查询结果将不包含其他ID与
IN
子句中的ID不同的其他标签您将获得所需的所有警报,但是标记将从结果中过滤掉-这很准确,您在这里看到的内容
您可以尝试将
root.join
替换为root.fetch
或尝试其他root.fetch
,但是我不确定两者是否都可以。关于java - JPA谓词标准构建器有很多麻烦,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57272108/