JPA多对多关联下按tagId查询Task出现重复记录如何解决?
重复原因
多对多关联join操作会产生笛卡尔积:当一个Workflow同时匹配tagId列表中多个Tag时,数据库会为同一个Task生成多条重复结果行,直接count就会统计到重复数据。另外原代码存在两处小问题:参数名不一致、直接对Tag实体做in判断,实际应该匹配Tag的id属性。
修正后的代码
public Long criteriaForCount(SearchCriteria searchCriteria) { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class); Root<Task> root = criteriaQuery.from(Task.class); List<Predicate> predicateList = new ArrayList<>(); // 修正参数名不一致问题:用方法入参searchCriteria替换原代码的taskSearchCriteria if(CoreUtil.isNonEmpty(searchCriteria.getTagIdList())) { // 修正in判断的匹配字段:取Tag的tagId属性匹配入参id列表 predicateList.add(root.join("workflow").join("tag").get("tagId").in(searchCriteria.getTagIdList())); } Predicate predicate = criteriaBuilder.and(predicateList.toArray(new Predicate[0])); criteriaQuery.where(predicate); // 核心修改:使用countDistinct对Task去重统计 criteriaQuery.select(criteriaBuilder.countDistinct(root)); return entityManager.createQuery(criteriaQuery).getSingleResult(); }
额外说明
如果你的业务场景是查询符合条件的Task实体列表而非计数,需要额外添加去重配置:
// 放在criteriaQuery.where调用之后即可 criteriaQuery.distinct(true);
如果项目配置了JPA静态元模型,建议将字符串形式的关联属性替换为元模型常量(比如Task_.workflow、Workflow_.tag、Tag_.tagId),可以避免属性名拼写错误的运行时问题。
内容的提问来源于stack exchange,提问作者Sparsh Verma
相关产品推荐
相关产品推荐

