如何在HQL中创建独立查询


100

有没有一种方法可以在HQL中创建一个Distinct查询。通过使用“ distinct”关键字或其他方法。我不确定distinct是否适用于HQL,但是我正在寻找与SQL关键字“ distinct”等效的HQL。

Answers:


124

这是我们使用的hql的片段。(名称已更改,以保护身份)

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});

我只在MySQL中使用过休眠-不知道如何处理mssql问题。
2012年

56

值得注意的是,distinctHQL中的关键字不会直接映射到distinctSQL中的关键字。

如果distinct在HQL中使用关键字,则有时Hibernate将使用distinctSQL关键字,但是在某些情况下,它将使用结果转换器产生不同的结果。例如,当您使用这样的外部联接时:

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

在这种情况下,不可能在SQL级别上过滤掉重复项,因此Hibernate 执行SQL查询之后使用a ResultTransformer来过滤重复项。



16

下次做这样的事情

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

 List claz = crit.list();

这不是最理想的:与其在数据库级别上丢弃重复,不如将包含重复和所有重复的数据从数据库中拉出到内存,然后再丢弃重复;根据数据重复的频率,可以大大增加I / O操作。
Haroldo_OK,

9

您也可以Criteria.DISTINCT_ROOT_ENTITY与Hibernate HQL查询一起使用。

例:

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

1
这不是最理想的:与其在数据库级别上丢弃重复,不如将包含重复和所有重复的数据从数据库中拉出到内存,然后再丢弃重复;根据数据重复的频率,可以大大增加I / O操作。
Haroldo_OK,

4

与HQL查询结合使用的结果转换器存在一些问题。当我尝试

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

它没有用。我不得不像这样手动转换:

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

使用Criteria API,转换器可以正常工作。


达到10k(:
timmz

3

我的主要查询在模型中如下所示:

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

而且我仍然没有得到我认为的“与众不同”的结果。它们只是基于表上的主键组合而不同。

因此,DaoImpl我在代码中添加了一行更改,最终得到了我想要的“独特”回报。一个例子是不要四次看到00,而现在只看到一次。这是我添加到的代码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;       
}

希望对您有所帮助!再一次,这只有在您遵循实现项目的服务,Dao和模型类型的编码实践时才可能有效。


2

假设您有一个映射到CUSTOMER_INFORMATION表的客户实体,并且您想要获取不同的firstname客户列表。您可以使用下面的代码片段来获取相同的内容。

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

希望对您有所帮助。因此,这里我们使用分组依据,而不是使用distinct关键字。

同样,以前,我发现很难将distinct关键字应用于多个列。例如,我想要获取不同的firstName,lastName然后由group by组成的列表将可以正常工作。在这种情况下,我很难使用distinct。


1

我有一个使用不同字段的Hibernate查询语言的答案。您可以使用* SELECT DISTINCT(TO_CITY)FROM FLIGHT_ROUTE *。如果使用SQL查询,它将返回字符串列表。您不能按实体类使用它的返回值。因此,解决此类问题的答案是将HQLSQL结合使用。

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

SQL查询语句中获得DISTINCT ROUTE_ID并输入为列表。IN查询从IN(列表)中过滤出不同的TO_CITY。

返回类型是实体Bean类型。因此,您可以在AJAX中使用它,例如AutoComplement

可能一切都好


1

您可以像这样在条件构建器中使用独特关键字。

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));

并在模型类中创建字段构造函数。


0

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

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

0

您可以简单地添加GROUP BY而不是Distinct

@Query(value = "from someTableEntity where entityCode in :entityCode" +
            " group by entityCode, entityName, entityType")
List<someTableEntity > findNameByCode(@Param("entityCode") List<String> entityCode);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.