gpt4 book ai didi

java - JPA 规范 + 多对多字段动态排序,不重复

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:00:57 26 4
gpt4 key购买 nike

我有一个包含很多字段、多对一和多对多关系的类,我需要按某些列(来自此类和连接类的字段)添加动态过滤器并添加排序这些字段也是如此。

我在按多对多字段进行过滤和排序时遇到问题

@Entity
class EntityA {
...
@ManyToMany
@JoinTable (
name = "EntityA_EntityB",
joinColumns = { @JoinColumn(name = "EntityB") },
inverseJoinColumns = { @JoinColumn(name = "entityb_id") }
)
private List<EntityB> bEntities;
...
}

我有通过 EntityB.name 过滤 EntityA 的规范(我设置了 criteriaQuery.distinct(true) 以防止重复,但我没有这个)

public class EntityASpecifications {
//other specifications
...

public static Specification<EntityA> entityBNameContains(String query) {
return (root, criteriaQuery, criteriaBuilder) -> {

if (query == null) {
return criteriaBuilder.conjunction();
}
criteriaQuery.distinct(true);

return getContainsPredicate(criteriaBuilder, root.join("bEntities").get("name"), query);
};
}

private static Predicate getContainsPredicate(CriteriaBuilder criteriaBuilder, Expression<String> field, String query) {

return (query == null) ? criteriaBuilder.conjunction() : criteriaBuilder.like(criteriaBuilder.lower(field), getContainsPattern(query));
}

private static String getContainsPattern(String searchTerm) {

return (searchTerm.isEmpty()) ? "%" : "%" + searchTerm.toLowerCase() + "%";
}
}

它工作正常,问题是当我尝试同时使用排序和这个过滤器时

entityARepository.findAll(EntityASpecifications.entityBNameContains("name"), PageRequest.of(page, size, Sort.Direction.ASC, sortColumnName));

作为 EntityB.name 连接到 EntityA 的字段失败(我还有一些其他带有 @ManyToOne 的字段失败)并出现下一个异常:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: ORDER BY items must appear in the select list if SELECT DISTINCT is specified

如果我删除 criteriaQuery.distinct(true);一切都会好起来的,但我会有重复的,我不想拥有它们

如何修复它并且不会同时出现重复的结果?

最佳答案

您获得 EntityA 的重复结果的原因是您将 EntityA 与 EntityB 结合在一起,并且您的谓词基于 EntityB 中的一个文件。因此,如果有多个 EntityB 条目满足您的条件,并且它们都属于同一个 EntityA,您将获得多个 EntityA 条目。所以解决方案是使用“存在”而不是连接两个表,你将不再需要使用 distinct。您的规范可以如下所示:

 public class EntityASpecifications {
//other specifications
...

public static Specification<EntityA> entityBNameContains(String query) {
return (root, criteriaQuery, criteriaBuilder) -> {

if (query == null) {
return criteriaBuilder.conjunction();
}
Subquery< EntityB> subquery = query.subquery(EntityB.class);
Root< EntityB> subqueryRoot = subquery.from(EntityB.class);
subquery.select(subqueryRoot);

subquery.where(criteriaBuilder.and(criteriaBuilder.equal(root, subqueryRoot.get("entitya_id")),
criteriaBuilder.like(criteriaBuilder.lower("name"), getContainsPattern(query)))
);

return criteriaBuilder.exists(subquery);

};
}
private static String getContainsPattern(String searchTerm) {
return (searchTerm.isEmpty()) ? "%" : "%" + searchTerm.toLowerCase() + "%";
}
}

关于java - JPA 规范 + 多对多字段动态排序,不重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53483937/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com