首页 > 解决方案 > 如何通过 Spring Data JPA 中的规范 API 查询多对多实体列表

问题描述

我有 2 个具有多对多关系的实体

   public class Enterprise{
        @Id
        @Column(name = "id", nullable = false, length = 50)
        @GeneratedValue(generator = "jpa-uuid")
        private String id;
        
        fields...
      
        @ManyToMany
        @JoinTable(name = "enterprise_to_tag",
                   joinColumns = @JoinColumn(name = "enterprise"), 
                   inverseJoinColumns = @JoinColumn(name = "tag"))
        private Set<EnterpriseTag> tags;
    }

public class EnterpriseTag{
    @Id
    @Column(name = "id", nullable = false, length = 50)
    @GeneratedValue(generator = "jpa-uuid")
    private String id;
    
    fields...

    @ManyToMany(mappedBy = "tags")
    private Set<Enterprise> enterprises;      
}

我想通过一些标签的ID查询企业列表,然后将它们打包到页面

private Page<Enterprise> searchEnterprise(int number, int size, String keyword, String tags, String county)
            throws BusinessException {
        validPageNumberAndPageSize(number, size);
        Pageable pageable = PageRequest.of(number, size);
        Specification<Enterprise> specification = (Specification<Enterprise>) (root, criteriaQuery, criteriaBuilder) -> {
            criteriaQuery.distinct(true);
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNoneBlank(keyword)) {
                Predicate predicateName = criteriaBuilder.like(root.get("name"), "%" + keyword + "%");
                Predicate predicateSerialNumber = criteriaBuilder.like(root.get("serialNumber"), "%" + keyword + "%");
               
                predicates.add(criteriaBuilder.and(criteriaBuilder.or(predicateName, predicateSerialNumber, predicateOrganizationCode)));
            }
            return criteriaQuery.where(predicates.toArray(new Predicate[0])).getRestriction();
        };
        //filter by tags here
        if (StringUtils.isNoneBlank(tags)) {
            List<String> tagIds = Arrays.asList(StringUtils.split(tags, ','));
            List<Enterprise> enterprises = enterpriseRepository.findAll(specification).stream().filter(enterprise ->
                    enterprise.getTags().stream().map(EnterpriseTag::getId).collect(Collectors.toList()).containsAll(tagIds))
                    .collect(Collectors.toList());
            return new PageImpl<>(enterprises, pageable, enterprises.size());
        } else {
            return enterpriseRepository.findAll(specification, pageable);
        }
    }

我不知道如何编写这个查询。我必须根据数据库查询结果来处理它。但这是有风险的。如果从数据库中查询的数据过多,会占用大量内存。请帮助我通过规范 API 编写此查询。谢谢。

标签: jpaspring-data-jpamany-to-many

解决方案


推荐阅读