Spring Data JPA Select Distinct

时间:2012-10-17 21:19:52

标签: java sql spring spring-data-jpa

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

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

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

5 个答案:

答案 0 :(得分:5)

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

规范被转换为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方法。

答案 1 :(得分:5)

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

在规范中,您可以访问查询,因此可以执行

query.distinct(true);

完整示例,导致发出此类SQL:

  

2015-04-27 12:03:39 EEST [7766-759] postgres @ sales LOG:执行   :SELECT DISTINCT t1.ID,t1.NAME,t1.WEBNAME,t1.WEBORDER,   t1.PVGROUPPARENT_ID,t1.SITE_ID来自PRODUCTVARIANT 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详情:   参数:$ 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);
        };
    }
}

答案 2 :(得分:3)

快速而肮脏的解决方案是使用Set

过滤结果
Set<...> set = new HashSet<...>( findAll( ... ) )

并确保equals()hashCode()在域类中相关实施: - )

干杯,

答案 3 :(得分:3)

好!您可以在distinct中使用JPQL,也可以在特定列中使用{{1}}。它已经here了。 参考Using DISTINCT in JPA

答案 4 :(得分:0)

这会有用吗?

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

然后通过列表迭代并使用Person.getAddress()?