Criteria.DISTINCT_ROOT_ENTITY 与 Projections.distinct

Posted

技术标签:

【中文标题】Criteria.DISTINCT_ROOT_ENTITY 与 Projections.distinct【英文标题】:Criteria.DISTINCT_ROOT_ENTITY vs Projections.distinct 【发布时间】:2014-10-21 14:40:35 【问题描述】:

我对 Hibernate 很陌生。我发现我们可以使用以下两种不同的方式获得不同的结果。谁能告诉我它们之间有什么区别?什么时候使用一个而不是另一个?

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

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

【问题讨论】:

【参考方案1】:

虽然名称相似,但用法不同。

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

这条语句将被翻译成 SQL 语句。它将传递给 DB Engine 并作为 SQL DISTINCT 执行。见:

17.9. Projections, aggregation and grouping

例如这个例子:

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

看起来像:

SELECT DISTINCT(cat_id) FROM cat_table

二。 criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

此语句事后执行。一旦从 DB 引擎返回 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。你用一个例子的回答让我很清楚。 我有一个疑问,你怎么能在它返回的第一个示例中创建类,而不仅仅是 id,你知道我的意思吗?谢谢。 我们可以使用 distinct id 并通过 HQL 使用它来从类中获取不同的行,但我认为这在性能方面不是一个好主意。 但是只有一只猫会同时拥有两只小猫吗? 我知道这已经很老了,但你能解释一下 DISTINCT_ROOT_ENTITY 在实际 SQL 术语中的作用吗?您在回答中描述它的方式是“您有一行 A,它是 1-n 并导致两行 B,您应用 DISTINCT_ROOT_ENTITY 并且它神奇地导致一行 B” - 如何?老实说,我很困惑如何在我正在构建的查询中复制它(与 java 无关)【参考方案2】:

来自文档: DISTINCT_ROOT_ENTITY 每行结果都是根实体的一个不同实例

distinct() 按属性选择不同的,在你的情况下按标识符

【讨论】:

感谢您的回复。我理解第二行,但由于缺乏对根实体的了解,我没有完全理解第一行。还是很有帮助的。

以上是关于Criteria.DISTINCT_ROOT_ENTITY 与 Projections.distinct的主要内容,如果未能解决你的问题,请参考以下文章