13

我有一种情况,我需要构建一个select distinct a.address from Person a(其中地址是个人内部的地址实体)类型的查询。

我正在使用规范来动态构建我的 where 子句并使用该findAll(Specification<T>)函数来获取结果。问题是我不能使用规范来构建我的选择子句,因此不能使用findAll(Spcification)函数。

做这样的事情的最好方法是什么?

4

5 回答 5

10

由于这是谷歌的首要问题,我将在这里发布答案。

在规范中您可以访问查询,因此您可以这样做

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);
        };
    }
}
于 2015-04-27T09:07:54.783 回答
6

我遇到了同样的问题,所以如果它对某人有帮助,这就是我所做的:

规范被翻译成 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);
    }

applySpecificationToCriteriaSimpleJpaRepository课堂上。

现在您可以使用该findDistinctValues方法了。

于 2015-01-06T14:35:13.707 回答
4

好的!您可以在特定列中使用distinctJPQL也可以在特定列中使用。它已经在这里了。参考在 JPA 中使用 DISTINCT

于 2012-10-18T07:57:21.870 回答
3

一个快速而肮脏的解决方案是使用 a 过滤结果Set

Set<...> set = new HashSet<...>( findAll( ... ) )

并确保equals()hashCode()在域类上相关实现:-)

干杯,

于 2012-10-18T07:37:40.290 回答
-2

这行得通吗?

List<Person> findDistinctPeopleByAddress(String lastname, String firstname);

然后遍历列表并使用 Person.getAddress() ?

于 2015-06-01T14:29:04.307 回答