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

时间:2012-03-26 12:24:14

标签: hibernate hql many-to-one

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


    @Entity
    @Table(name="request")
    public class Request implements Serializable {
        private int id;
        private User requester;

        @Id
        @Column(name="ID", unique=true, nullable=false)
        public int getId() {
            return this.id;
        }

        @ManyToOne(fetch=FetchType.EAGER)
        @JoinColumn(name="REQUESTER", nullable=false)
        public User getRequester() {
            return this.requester;
        }
    }

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

我尝试了以下内容:


    public List<User> retrieveAllRequesters() {
        return hbSession().createQuery("select requester from Request r left join r.requester as requester").list();
    }

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

我尝试添加 distinct 关键字,如下所示:


       select distinct requester from Request r left join r.requester as requester

但是这导致了HQL语法错误

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

我很欣赏HQL建议我做我需要的东西。感谢。

Bohemian建议这可能是一个方言问题,所以我启用了hibernate.show_sql,它显示如下:

Hibernate: 
    select
        distinct user1_.ID as ID10_,
        user1_.EMAIL_ADDRESS as EMAIL2_10_,
        user1_.EXTERNAL_ID as EXTERNAL3_10_,
        user1_.IS_ADMINISTRATOR as IS4_10_,
        user1_.IS_SUPERVISOR as IS5_10_,
        user1_.IS_TECHNICIAN as IS6_10_,
        user1_.LAST_CHECKED_IN_AT as LAST7_10_,
        user1_.LAST_LOGGED_IN_AT as LAST8_10_,
        user1_.LAST_UPDATED_AT as LAST9_10_,
        user1_.NAME as NAME10_,
        user1_.UI_PREFERENCES as UI11_10_ 
    from
        request request0_ 
    inner join
        [user] user1_ 
            on request0_.REQUESTER=user1_.ID
2255 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 421, SQLState: S0001
2255 [main] ERROR org.hibernate.util.JDBCExceptionReporter - The text data type cannot be selected as DISTINCT because it is not comparable.

数据库是MS SQL Server。

2 个答案:

答案 0 :(得分:3)

使用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

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

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

答案 1 :(得分:0)

非常感谢波西米亚人指出我正确的方向。他的出色答案值得更多投票。

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

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

    public List<Object[]> retrieveAllRequesters() {
        return hbSession().createQuery("select distinct r.requester.id, r.requester.name from Request r").list();
    }