我有一种情况,我需要构建一个select distinct a.address from Person a
(其中地址是个人内部的地址实体)类型的查询。
我正在使用规范来动态构建我的 where 子句并使用该findAll(Specification<T>)
函数来获取结果。问题是我不能使用规范来构建我的选择子句,因此不能使用findAll(Spcification)
函数。
做这样的事情的最好方法是什么?
我有一种情况,我需要构建一个select distinct a.address from Person a
(其中地址是个人内部的地址实体)类型的查询。
我正在使用规范来动态构建我的 where 子句并使用该findAll(Specification<T>)
函数来获取结果。问题是我不能使用规范来构建我的选择子句,因此不能使用findAll(Spcification)
函数。
做这样的事情的最好方法是什么?
由于这是谷歌的首要问题,我将在这里发布答案。
在规范中您可以访问查询,因此您可以这样做
query.distinct(true);
完整的示例,导致发出这样的 SQL:
2015-04-27 12:03:39 EEST [7766-759] postgres@sales 日志:执行:从 PRODUCTVARIANT 中选择 DISTINCT t1.ID、t1.NAME、t1.WEBNAME、t1.WEBORDER、t1.PVGROUPPARENT_ID、t1.SITE_ID t0, PVGROUP t1 WHERE ((t0.PRODUCTTYPE_ID = $1) AND (t0.PVGROUP_ID = t1.ID)) 2015-04-27 12:03:39 EEST [7766-760] postgres@sales DETAIL: 参数: $1 = ' 4608bdc9-d0f2-4230-82fd-b0f776dc2cfd'
public static Specification<PVGroup> byProductType(final ProductType pt) {
return (final Root<PVGroup> root, final CriteriaQuery<?> query, final CriteriaBuilder builder) -> {
query.distinct(true);
final CollectionJoin<PVGroup, ProductVariant> jPV = root.join(PVGroup_.productVariant);
final Path<ProductType> ptPath = jPV.get(ProductVariant_.productType);
return builder.equal(ptPath, pt);
};
}
}
我遇到了同样的问题,所以如果它对某人有帮助,这就是我所做的:
规范被翻译成 where 子句,findAll(Specification<T>)
函数正在创建自己的 select 子句。因此,我们无法通过某种方式使用该findAll(Specification<T>)
函数来解决此问题。我已经有扩展的自定义存储库SimpleJpaRepository
,所以我添加了一个新方法:
@Override
@Transactional(readOnly = true)
public List<Object> findDistinctValues(Specifications<T> spec, String columnName) {
return getQuery(spec, columnName).getResultList();
}
protected TypedQuery<Object> getQuery(Specification<T> spec, final String distinctColumnName) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Object> query = builder.createQuery(Object.class);
Root<T> root = applySpecificationToCriteria(spec, query);
if (null != distinctColumnName) {
query.distinct(true);
query.multiselect(root.get(distinctColumnName));
}
// We order by the distinct column, Asc
query.orderBy(builder.asc(root.get(distinctColumnName)));
return em.createQuery(query);
}
applySpecificationToCriteria
在SimpleJpaRepository
课堂上。
现在您可以使用该findDistinctValues
方法了。
好的!您可以在特定列中使用distinct
,JPQL
也可以在特定列中使用。它已经在这里了。参考在 JPA 中使用 DISTINCT
一个快速而肮脏的解决方案是使用 a 过滤结果Set
:
Set<...> set = new HashSet<...>( findAll( ... ) )
并确保equals()
并hashCode()
在域类上相关实现:-)
干杯,
这行得通吗?
List<Person> findDistinctPeopleByAddress(String lastname, String firstname);
然后遍历列表并使用 Person.getAddress() ?