当尝试获取属性(即实体)及其值的计数时,HQL 出现问题

发布于 2024-11-03 06:50:31 字数 1887 浏览 0 评论 0原文

在我的项目中,我有两个实体,第一个 PaperEntity 包含多个属性(由值类型和引用类型 - 对其他实体的引用 - 组成),第二个是 PaperStatusEntity。 PaperEntity 有一个名为 PaperStatusEntity 类型的 Result 属性(还有一个名为 lock 的 bool 类型属性)

假设您有近 500 篇论文,而数据库中只定义了 8 个论文状态。 我想知道每种状态的使用量是多少?例如,status1 使用了 58 次,status2 使用了 130 次,依此类推。 我在 HQL 下写下,

select paper.Result, Count(paper.Result) from PaperEntity paper group by paper.Result

此 hql 生成以下错误:

Column 'Conference_PaperStatusesTable.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 

生成的 sql 是:

select paperentit0_.Result as col_0_0_, count(paperentit0_.Result) as col_1_0_, paperstatu1_.Id as Id48_, paperstatu1_.Version as Version48_, paperstatu1_.CreationTime as Creation3_48_, paperstatu1_.Portal as Portal48_, paperstatu1_.TitleCodeName as TitleCod5_48_, paperstatu1_.Enabled as Enabled48_, paperstatu1_.RefereeChoice as RefereeC7_48_, paperstatu1_.OrderIndex as OrderIndex48_, paperstatu1_.ContactMessageTemplate as ContactM9_48_ from Conference_PapersTable paperentit0_ inner join Conference_PaperStatusesTable paperstatu1_ on paperentit0_.Result=paperstatu1_.Id, Conference_PaperStatusesTable paperstatu2_ where paperentit0_.Result=paperstatu2_.Id group by paperentit0_.Result 

如果我尝试使用“Locked”(即 bool)之类的值类型属性对数据进行分组,则没有问题,所有事情

也都可以如果我使用 Criteria 而不是 HQL ,真正有效:

IList result = NHibernateSessionManager.Instance.CurrentSession.CreateCriteria(typeof(PaperEntity))
                .SetProjection(Projections.ProjectionList().Add(Projections.RowCount()).Add(Projections.GroupProperty("Result"))).List();

foreach (var item in result) {
        object[] value = item as object[];
        yield return new Pair<PaperStatusEntity, int>(value[1] as PaperStatusEntity, (int)value[0]);
    }

In my project, I have two entity, first PaperEntity contains several properties (consisting of value types and also reference types -reference to other entities-) and second is PaperStatusEntity.
PaperEntity has a property named Result of type PaperStatusEntity (and also a property named locked of type bool)

Imagine you have near 500 papers and just 8 paper status defined in database.
I want to find how much every status is used? for example status1 used 58 times and status2 used 130 times and so on.
I write below HQL

select paper.Result, Count(paper.Result) from PaperEntity paper group by paper.Result

this hql generates below error:

Column 'Conference_PaperStatusesTable.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 

generated sql is:

select paperentit0_.Result as col_0_0_, count(paperentit0_.Result) as col_1_0_, paperstatu1_.Id as Id48_, paperstatu1_.Version as Version48_, paperstatu1_.CreationTime as Creation3_48_, paperstatu1_.Portal as Portal48_, paperstatu1_.TitleCodeName as TitleCod5_48_, paperstatu1_.Enabled as Enabled48_, paperstatu1_.RefereeChoice as RefereeC7_48_, paperstatu1_.OrderIndex as OrderIndex48_, paperstatu1_.ContactMessageTemplate as ContactM9_48_ from Conference_PapersTable paperentit0_ inner join Conference_PaperStatusesTable paperstatu1_ on paperentit0_.Result=paperstatu1_.Id, Conference_PaperStatusesTable paperstatu2_ where paperentit0_.Result=paperstatu2_.Id group by paperentit0_.Result 

If I try to group data with a value type property like 'Locked' (that is bool), no problems and all things are ok

also If I use Criteria instead of HQL, works truly:

IList result = NHibernateSessionManager.Instance.CurrentSession.CreateCriteria(typeof(PaperEntity))
                .SetProjection(Projections.ProjectionList().Add(Projections.RowCount()).Add(Projections.GroupProperty("Result"))).List();

foreach (var item in result) {
        object[] value = item as object[];
        yield return new Pair<PaperStatusEntity, int>(value[1] as PaperStatusEntity, (int)value[0]);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烂柯人 2024-11-10 06:50:31

HQL group by 不够智能,无法在按实体分组时投影实体的所有属性。您必须:

  • 指定所有属性
  • 仅选择您需要的属性(id、描述等)
  • 使用子查询获取计数

它与 Criteria 一起使用的原因是它在以下情况下仅选择 id:您使用 Projections.GroupProperty 创建未初始化的代理。

这可能会产生 SELECT N+1 问题。

HQL group by is not smart enough to project all the properties of an entity when grouping by it. You have to either:

  • Specify all the properties
  • Select just those you need (id, description, whatever)
  • Use a subquery to get the count

The reason why it's working with Criteria is that it selects just the id when you use Projections.GroupProperty, creating uninitialized proxies.

This can create a SELECT N+1 problem.

明月松间行 2024-11-10 06:50:31

您需要提供一个简单的数据类型供数据库引擎进行分组。如果 paper.Result 是另一个实体,您可能需要加入 PaperStatusEntity 表。

类似于:

select paper.Result, Count(paper.Result) 
from PaperEntity as paper 
join paper.Result as status
group by status.Id

如果 PaperStatus 映射为组件,您还可以直接访问 Result.Id。

You need to provide a simple data type for the database engine to group by. If paper.Result is another entity you'll probably need to join to the PaperStatusEntity table.

Something like:

select paper.Result, Count(paper.Result) 
from PaperEntity as paper 
join paper.Result as status
group by status.Id

If PaperStatus is mapped as a component you can also access Result.Id directly.

无边思念无边月 2024-11-10 06:50:31

您可以尝试:

SELECT paper.Result, Count(paper.Result) 
FROM PaperEntity paper
JOIN paper.Result as status
GROUP BY paper.Result

请注意,您宁愿使用“FROM PaperStatusEntity”并加入论文
因为在您尝试执行的实际操作中,如果没有论文使用此状态,您可能无法获得 PaperStatusEntity 的计数(这意味着您不会获得计数 = 0,您只是没有获得计数)

您还可以使用@Formula 注释,这样,对于给定的状态,您可以执行 paperStatusEntity.getPaperNumber()

只需添加类似的内容

@Formula("select count() from PaperEntity paper where paper.result_id = id");
public int getPaperNumber();

(应该进行调整)

(我使用 Hibernate 但它应该是相同的?)

You can try:

SELECT paper.Result, Count(paper.Result) 
FROM PaperEntity paper
JOIN paper.Result as status
GROUP BY paper.Result

Note that you would rather use a "FROM PaperStatusEntity" and join the papers
Because with the actual thing you are trying to do, you may not get a count for a PaperStatusEntity if no paper use this status (this means you don't get a count=0, you just get no count)

You can also use the @Formula annotation so that, for a given status, you can do paperStatusEntity.getPaperNumber()

Just add something like

@Formula("select count() from PaperEntity paper where paper.result_id = id");
public int getPaperNumber();

(should be adapted)

(I use Hibernate but it should be the same?)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文