简体   繁体   English

如何在 HQL 中创建 Distinct 查询

[英]How do you create a Distinct query in HQL

Is there a way to create a Distinct query in HQL.有没有办法在 HQL 中创建一个 Distinct 查询。 Either by using the "distinct" keyword or some other method.通过使用“distinct”关键字或其他一些方法。 I am not sure if distinct is a valid keywork for HQL, but I am looking for the HQL equivalent of the SQL keyword "distinct".我不确定 distinct 是否是 HQL 的有效关键字,但我正在寻找与 SQL 关键字“distinct”等效的 HQL。

Here's a snippet of hql that we use.这是我们使用的 hql 片段。 (Names have been changed to protect identities) (名称已更改以保护身份)

String queryString = "select distinct f from Foo f inner join foo.bars as b" +
                " where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
        return getHibernateTemplate().find(queryString, new Object[] {startDate, endDate, bar});

It's worth noting that the distinct keyword in HQL does not map directly to the distinct keyword in SQL.值得注意的是,HQL 中的distinct关键字不会直接映射到 SQL 中的distinct关键字。

If you use the distinct keyword in HQL, then sometimes Hibernate will use the distinct SQL keyword, but in some situations it will use a result transformer to produce distinct results.如果在 HQL 中使用distinct关键字,那么有时 Hibernate 会使用distinct SQL 关键字,但在某些情况下,它会使用结果转换器来产生不同的结果。 For example when you are using an outer join like this:例如,当您使用这样的外连接时:

select distinct o from Order o left join fetch o.lineItems

It is not possible to filter out duplicates at the SQL level in this case, so Hibernate uses a ResultTransformer to filter duplicates after the SQL query has been performed.在这种情况下,不可能在 SQL 级别过滤掉重复项,因此 Hibernate 使用ResultTransformer执行 SQL 查询过滤重复项。

do something like this next time下次做这样的事情

 Criteria crit = (Criteria) session.
                  createCriteria(SomeClass.class).
                  setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

 List claz = crit.list();

You can also use Criteria.DISTINCT_ROOT_ENTITY with Hibernate HQL query as well.您还可以将Criteria.DISTINCT_ROOT_ENTITY与 Hibernate HQL 查询一起使用。

Example:例子:

Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();

I had some problems with result transformers combined with HQL queries.我在将结果转换器与 HQL 查询结合使用时遇到了一些问题。 When I tried当我尝试

final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);

it didn't work.它没有用。 I had to transform manually like this:我不得不像这样手动转换:

final List found = trans.transformList(qry.list());

With Criteria API transformers worked just fine.使用 Criteria API 转换器工作得很好。

My main query looked like this in the model:我的主要查询在模型中如下所示:

@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd", 
    query = "select distinct i from CentralFinancialAgencyAccountCd i")

And I was still not getting what I considered "distinct" results.我仍然没有得到我认为“不同”的结果。 They were just distinct based on a primary key combination on the table.它们只是基于桌子上的主键组合而不同。

So in the DaoImpl I added an one line change and ended up getting the "distinct" return I wanted.因此,在DaoImpl我添加了一行更改,最终得到了我想要的“不同”回报。 An example would be instead of seeing 00 four times I now just see it once.一个例子是,我现在只看到一次,而不是看到四次 00。 Here is the code I added to the DaoImpl :这是我添加到DaoImpl的代码:

@SuppressWarnings("unchecked")
public List<CacheModelBase> getAllCodes() {

    Session session = (Session) entityManager.getDelegate();
    org.hibernate.Query q = session.getNamedQuery("getAllCentralFinancialAgencyAccountCd");
    q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // This is the one line I had to add to make it do a more distinct query.
    List<CacheModelBase> codes;
    codes = q.list();
    return codes;       
}

I hope this helped!我希望这有帮助! Once again, this might only work if you are following coding practices that implement the service, dao, and model type of project.同样,这可能只有在您遵循实现服务、dao 和项目模型类型的编码实践时才有效。

Suppose you have a Customer Entity mapped to CUSTOMER_INFORMATION table and you want to get list of distinct firstName of customer.假设您有一个映射到 CUSTOMER_INFORMATION 表的客户实体,并且您想要获取客户的不同名字的列表。 You can use below snippet to get the same.您可以使用以下代码段来获得相同的结果。

Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();

I hope it helps.我希望它有帮助。 So here we are using group by instead of using distinct keyword.所以这里我们使用 group by 而不是使用 distinct 关键字。

Also previously I found it difficult to use distinct keyword when I want to apply it to multiple columns.以前我也发现当我想将其应用于多列时很难使用不同的关键字。 For example I want of get list of distinct firstName, lastName then group by would simply work.例如,我想要获取不同的 firstName、lastName 列表,然后 group by 就可以了。 I had difficulty in using distinct in this case.在这种情况下,我很难使用 distinct 。

You can you the distinct keyword in you criteria builder like this.您可以像这样在标准构建器中使用不同的关键字。

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Orders> query = builder.createQuery(Orders.class);
Root<Orders> root = query.from(Orders.class);
query.distinct(true).multiselect(root.get("cust_email").as(String.class));

And create the field constructor in your model class.并在您的模型类中创建字段构造函数。

I have got a answer for Hibernate Query Language to use Distinct fields.我得到了 Hibernate Query Language 使用 Distinct 字段的答案。 You can use *SELECT DISTINCT(TO_CITY) FROM FLIGHT_ROUTE*.您可以使用 *SELECT DISTINCT(TO_CITY) FROM FLIGHT_ROUTE*。 If you use SQL query, it return String List.如果使用SQL查询,则返回字符串列表。 You can't use it return value by Entity Class.您不能通过实体类使用它返回值。 So the Answer to solve that type of Problem is use HQL with SQL .所以解决这类问题的答案是使用HQLSQL

FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);

From SQL query statement it got DISTINCT ROUTE_ID and input as a List.SQL查询语句它得到 DISTINCT ROUTE_ID 并作为列表输入。 And IN query filter the distinct TO_CITY from IN (List).和 IN 查询从 IN(列表)过滤不同的 TO_CITY。

Return type is Entity Bean type.返回类型是实体 Bean 类型。 So you can it in AJAX such as AutoComplement .所以你可以在 AJAX 中使用它,比如AutoComplement

May all be OK愿一切都好

如果您需要在 select 语句中为自定义 DTO 使用new关键字并且需要不同的元素,请在 new 之外使用 new ,如下所示 -

select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...

You can simply add GROUP BY instead of Distinct您可以简单地添加 GROUP BY 而不是 Distinct

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM