有人可以向我解释为什么Spring使用规范功能检查可分页LEFT JOIN
Order
吗?
情况如下:
我想使用Spring规范生成用于过滤数据的动态查询,并且可分页以限制数据。查询位于UserEntity
和UserGroupEntity
之间,我希望始终在每个查询上获取UserGroupEntity
,因此我为COUNT
和数据查询添加了一个检查块。如果查询是查询COUNT
,那么我使用Join
对象,否则我使用Fetch
对象。
public static Specification<UserEntity> filtered(final String searchTerm) {
return new Specification<UserEntity>() {
@SuppressWarnings("unchecked")
@Override
public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Join<UserEntity, UserGroupEntity> joinUserGroup = null;
if (QueryHelper.isQueryCount(query)) {
joinUserGroup = root.join("userGroup");
} else {
Fetch<UserEntity, UserGroupEntity> fetchUserGroup = root.fetch("userGroup");
joinUserGroup = (Join<UserEntity, UserGroupEntity>) fetchUserGroup;
}
if (searchTerm != null) {
List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(cb.like(root.get("lowerUsername").as(String.class), "%" + searchTerm.toLowerCase() + "%"));
predicates.add(cb.like(root.get("lowerEmail").as(String.class), "%" + searchTerm.toLowerCase() + "%"));
predicates.add(cb.like(joinUserGroup.get("lowerName").as(String.class), "%" + searchTerm.toLowerCase() + "%"));
cb.or(predicates.toArray(new Predicate[predicates.size()]));
}
return null;
}
};
}
这就是我在UserService
上调用规范的方式:
Order order = new Order(Direction.ASC, "lowerEmail");
Page<UserEntity> pages = userRepository.findAll(filtered(searchTerm), new PageRequest(page, size, new Sort(order)));
使用UserEntity
列添加排序时,查询正常。这是生成的HQL:
select generatedAlias0 from com.example.entity.UserEntity as generatedAlias0
inner join fetch generatedAlias0.userGroup as generatedAlias1
order by generatedAlias0.lowerEmail asc
但当我使用连接实体中的列进行排序userGroup.lowerName
时,查询变得奇怪(因为我不知道为什么)。通过使用该列,Spring在我的查询中添加了更多LEFT JOIN
并使其像这样:
select generatedAlias0 from com.example.entity.UserEntity as generatedAlias0
left join generatedAlias0.userGroup as generatedAlias1
inner join fetch generatedAlias0.userGroup as generatedAlias2
order by generatedAlias1.lowerName asc
当我在Github上看到spring-data-JPA代码时,我发现从specification
到criteria
的转换是在方法getQuery()
中完成的。此方法调用类toOrders()
中的其他方法QueryUtils
以应用排序顺序。方法toOrders()
最终调用方法getOrCreateJoin()
或isAlreadyFetched()
,它将检查前一个连接属性(我在规范中创建的属性)userGroup
,但是因为连接类型不是LEFT JOIN
然后Spring在我的查询中使用LEFT JOIN
添加了更多连接。
private static Join<?, ?> getOrCreateJoin(From<?, ?> from, String attribute) {
for (Join<?, ?> join : from.getJoins()) {
boolean sameName = join.getAttribute().getName().equals(attribute);
if (sameName && join.getJoinType().equals(JoinType.LEFT)) {
return join;
}
}
return from.join(attribute, JoinType.LEFT);
}
这是我在spring-data-jpa
代码CMIIW上搜索得到的内容。 JoinType.LEFT
的目的是什么,实际上我还是不明白。你的解释对我(和我们)非常有帮助。
现在我认为我将使用自定义存储库使用JPQL生成动态查询,直到我使用LEFT JOIN
和specification
了解生成的查询与其他pageable
的原因。
答案 0 :(得分:0)
我遇到了同样的问题,并在https://stackoverflow.com/a/43965633/7280115中找到了解决方案和答案。您可以检查它是否也适合您