Criteria.DISTINCT_ROOT_ENTITY和Projections.distinct的区别

46

我对Hibernate还比较陌生。我发现我们可以使用以下两种不同的方式获得不同的结果。有人能告诉我它们之间的区别吗?何时使用其中一种而不是另一种?

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

对抗

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
2个回答

92

虽然名称相似,但使用方式不同。

I. Projections.distinct(Projections.property("id"));

该语句将被翻译为SQL语句,并传递给DB引擎作为SQL DISTINCT执行。参见:

例如,这个例子:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.distinct(Projections.property("id")) )
    )
    .list();
似乎应该是:

看起来好像:

SELECT DISTINCT(cat_id) FROM cat_table

II. criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

这条语句是在SQL查询结果返回后事后执行的。Hibernate迭代结果集将其转换为我们实体列表。

但是它总是需要吗?不是的,大多数情况下不需要使用它。

唯一需要使用它的情况是,如果查询中存在关联 - 加入one-to-many端。

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

SELECT cat.*, kitten.*
FROM cat_table as cat 
  INNER JOIN kitten_table kitten ON kitten.cat_id = cat.cat_id

所以,在criteriaQuery的结尾陈述:

... // criteriaQuery joining root and some one-to-many
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)

这将导致一个只有一只猫的列表。


非常感谢您清晰的回答,解释得非常好。我已经快读完《Beginning Hibernate》这本书了,但我仍然无法理解Criteria.DISTINCT_ROOT_ENTITY是什么意思。您的回答和示例让我明白了。 - user3123690
1
我有一个疑问,第一个例子中如何使其返回类而不仅仅是ID,你知道我的意思吗?谢谢。 - Alberto Acuña
我们可以使用唯一标识符,并使用HQL从类中获取不同的行,但我认为这在性能方面不是一个好主意。 - MR AND
1
但是这只猫会同时拥有两只小猫吗? - Alexander Arutinyants
我知道这很古老,但您能否用实际的 SQL 术语解释 DISTINCT_ROOT_ENTITY 是做什么用的?您在答案中描述的方式是“您有一行 A,它是1-n,并且会产生两行 B,您应用 DISTINCT_ROOT_ENTITY,它就会神奇地变成一行 B”-为什么?我真的不知道如何在我正在构建的查询中复制它(与 Java 无关)。 - Eskir

3

来自文档: DISTINCT_ROOT_ENTITY 结果中的每一行都是根实体的唯一实例

distinct() 按属性选择唯一值,对于您的情况是按标识符选择唯一值


谢谢您的回复。我理解了第二行,但由于对根实体缺乏知识,我并没有完全理解第一行。不过这仍然非常有帮助。 - user3123690

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接