在JPQL或JPA条件构建器中进行DISTINCT ON

时间:2014-12-26 11:39:13

标签: jpa distinct jpql

我有一个JPA实体用户,其中包含一个字段(实体)城市。我想选择一个页面,例如10个用户,但来自不同的城市。

在SQL中我会使用类似的东西:

SELECT DISTINCT ON (u.city_id) u.username ,u.email, u.city_id ....
FROM user u LIMIT 0,10 ....

但我需要使用JPQL或JPA条件构建器。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:3)

You can do this by using Hibernate Criteria Query 

sample code can be like this 




 Criteria criteria = session.createCriteria(user.class);
 ProjectionList projectionList = Projections.projectionList();
           projectionList.add(Projections.distinct(projectionList.add(Projections.property("city_id"),  "cityId")));
      projectionList.add(Projections.property("username"), "username");
     projectionList.add(Projections.property("email"), "email");
      criteria.setProjection(projectionList2);
     criteria.setResultTransformer(Transformers.aliasToBean(user.class)); 
     List list = criteria.list();

答案 1 :(得分:1)

最近遇到了同样的情况,发现没有直接的方法用criteria查询来支持。

这是我的解决方案 -

<块引用>
  • 为distinct on创建自定义sql函数
  • 注册方言函数
  • 更新属性中的方言
  • 从条件查询中调用

1) 创建自定义函数

public class DistinctOn implements SQLFunction {
    @Override
    public boolean hasArguments() {
        return true;
    }

    @Override
    public boolean hasParenthesesIfNoArguments() {
        return true;
    }

    @Override
    public Type getReturnType(Type type, Mapping mapping) throws QueryException {
        return StandardBasicTypes.STRING;
    }

    @Override
    public String render(Type type, List arguments, SessionFactoryImplementor sessionFactoryImplementor) throws QueryException {
        if (arguments.size() == 0) {
            throw new QueryException("distinct on should have at least one argument");
        }
        String commaSeparatedArgs = String.join(",",arguments);
        return " DISTINCT ON( " + commaSeparatedArgs + ") " + arguments.get(0) + " ";
    }
}

2) 注册函数

public class CustomPostgresSqlDialect extends PostgreSQLDialect {
    public CustomPostgresSqlDialect() {
        super();
        registerFunction("DISTINCT_ON", new DistinctOn());
    }
}

3) 更新方言: 在这里传递你的班级名称

spring.jpa.properties.hibernate.dialect = com.harshal.common.CustomPostgresSqlDialect

4) 在条件查询中使用它

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
        
// SELECT DISTINCT ON (u.city_id) u.username 
query.multiselect(
    cb.function("DISTINCT_ON", String.class, user.get("city")),
    user.get("userName")
);
        
return em.createQuery(query).getResultList();