HQL 检索多对一关系中不同实体的列表

Posted

技术标签:

【中文标题】HQL 检索多对一关系中不同实体的列表【英文标题】:HQL to retrieve list of distinct entities in many to one relationship 【发布时间】:2012-04-09 22:50:48 【问题描述】:

在我的应用程序中,用户可以生成对事物的请求,因此我有两个实体 Request 和 User 映射到同名的基础表。存在多对一关系,因此用户可以提出许多请求。因此,我的请求实体看起来像这样

@实体 @Table(name="请求") 公共类请求实现可序列化 私人 int id; 私人用户请求者; @ID @Column(name="ID", unique=true, nullable=false) 公共 int getId() 返回这个.id; @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="REQUESTER", nullable=false) 公共用户 getRequester() 返回 this.requester;

我需要获取至少提出一个请求的所有用户的列表。

我尝试了以下方法:

公共列表retrieveAllRequesters() return hbSession().createQuery("select requester from Request r left join r.requester as requester").list();

但这会为每个请求返回一个实体

我尝试像这样添加 distinct 关键字:

从 Request r 中选择不同的请求者 left join r.requester as requester

但这会导致 HQL 语法错误

我尝试了很多其他方法,将 left 连接更改为 innerouter,但没有成功。

我很感激 HQL 能做我需要做的事情的建议。谢谢。

Bohemian 建议这可能是方言问题,所以我启用了 hibernate.show_sql 并显示以下内容:

休眠: 选择 不同的 user1_.ID 为 ID10_, user1_.EMAIL_ADDRESS 作为 EMAIL2_10_, user1_.EXTERNAL_ID 为 EXTERNAL3_10_, user1_.IS_ADMINISTRATOR 作为 IS4_10_, user1_.IS_SUPERVISOR 为 IS5_10_, user1_.IS_TECHNICIAN 作为 IS6_10_, user1_.LAST_CHECKED_IN_AT 作为 LAST7_10_, user1_.LAST_LOGGED_IN_AT 作为 LAST8_10_, user1_.LAST_UPDATED_AT 作为 LAST9_10_, user1_.NAME 作为 NAME10_, user1_.UI_PREFERENCES 作为 UI11_10_ 从 请求请求0_ 内部联接 [用户] user1_ 在 request0_.REQUESTER=user1_.ID 2255 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL 错误:421,SQLState:S0001 2255 [main] 错误 org.hibernate.util.JDBCExceptionReporter - 文本数据类型无法选择为 DISTINCT,因为它不可比较。

数据库是 MS SQL Server。

【问题讨论】:

【参考方案1】:

使用 HQL,您不需要“加入” - 它已经隐式加入。试试这个:

return hbSession()
   .createQuery("select distinct r.requester from Request r")
   .list();

已编辑

从最近补充的问题来看,重点是:

The text data type cannot be selected as DISTINCT because it is not comparable

这似乎是来自 microsoft *sigh* 的又一点蹩脚代码(我曾经使用过的每个数据库都可以处理它 - 这只是我从未使用过 MS SQL 的另一个原因)

您必须将 text 列的数据类型更改为 varchar(something),在它们上使用 substring(1, n)(在 HQL 中)以将它们缩短为某种东西可怜的 MS SQL 可以“比较”

【讨论】:

谢谢。我刚刚尝试过,但我得到了添加 distinct 关键字时得到的 SQLGrammarException。如果我删除 distinct 则不会出现异常,但随后我会为每个请求获得一行 应该可以(过去对我有用)。听起来像一个错误或方言不匹配。你用的是什么数据库,什么方言? MS-Sql Server(最新版本)方言是org.hibernate.dialect.SQLServerDialect 只要requestor 是单个对象(不是集合等),这应该可以工作。除了“祝你好运”,我不知道还能说什么 我已启用 hibernate.show_sql,它显示了一些我将添加到我的问题中的更多信息【参考方案2】:

非常感谢 Bohemian 为我指明了正确的方向。他的出色回答值得更多投票。

是的,这是 MS SQL Server 的一个限制,特别是它无法处理具有 distinct 的“文本”字段,但更多的是我不明白 distinct 将比较它返回的实体中的所有字段,而不仅仅是 ID 字段。

因此,我的答案是重新配置我的 HQL,以便它只返回我感兴趣的字段,而不是整个用户实体。这是它现在的样子:

公共列表检索所有请求者() return hbSession().createQuery("select distinct r.requester.id, r.requester.name from Request r").list();

【讨论】:

以上是关于HQL 检索多对一关系中不同实体的列表的主要内容,如果未能解决你的问题,请参考以下文章

JPA - 如何在多对一关系中检查条件

核心数据获取多对一关系对象

django - 从多对一关系中获取对象集

Django 在多对一关系中引用特定对象

hibernate多对一关联映射两种形式的理解

Django models 多对一关系中 on_delete 参数的设置