Criteria.DISTINCT_ROOT_ENTITY与Projections.distinct

use*_*690 40 nhibernate hibernate distinct hibernate-criteria

我对Hibernate很新.我发现我们可以使用以下两种不同的方式获得不同的结果.谁能告诉我他们之间有什么区别?何时使用其他?

Projections.distinct(Projections.property("id"));
Run Code Online (Sandbox Code Playgroud)

VS

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
Run Code Online (Sandbox Code Playgroud)

Rad*_*ler 81

虽然名字相似,但用法不同.

一世. Projections.distinct(Projections.property("id"));

此语句将转换为SQL语句.它将被传递给DB Engine并作为SQL执行DISTINCT.看到:

所以例如这个例子:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.distinct(Projections.property("id")) )
    )
    .list();
Run Code Online (Sandbox Code Playgroud)

似乎是:

SELECT DISTINCT(cat_id) FROM cat_table
Run Code Online (Sandbox Code Playgroud)

II. criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

该声明在事后执行.一旦返回来自数据库引擎的SQL查询,Hibernate就会迭代结果集,将其转换为我们实体的列表.

但它总是需要吗?不,大多数情况下这不是必需的.

唯一的情况,当我们必须使用它时,如果查询中存在关联 - 加入one-to-many结束.

因为如果我们确实有一个cat和它的两个kittens,这将返回2行,而cat只有一个:

SELECT cat.*, kitten.*
FROM cat_table as cat 
  INNER JOIN kitten_table kitten ON kitten.cat_id = cat.cat_id
Run Code Online (Sandbox Code Playgroud)

所以,最后的声明criteriaQuery:

... // criteriaQuery joining root and some one-to-many
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
Run Code Online (Sandbox Code Playgroud)

会产生一个只有一只猫的清单.