Grails HQL表示查询

时间:2015-11-05 14:11:51

标签: mysql grails hql gorm

我在HQL中代表以下MySQL查询

SELECT t1.id as user_id, t2.id as follow_id
FROM user t1
INNER JOIN follows t2 ON 
    (t2.follower_id = <user id> AND t2.followee_id = t1.id) OR
    (t2.follower_id = t1.id AND t2.followee_id = <user id>)
WHERE t1.active = true
ORDER BY t1.id

你能帮我解决一下这个问题吗?

谢谢!

修改

到目前为止,我已尝试过以下HQL查询,但无法返回正确的数据:

SELECT t1
FROM User t1
JOIN t1.follows t2
JOIN t2.follower follower
JOIN t2.followee followee
WHERE (follower.id = :usr AND followee.id = t1.id) OR
    (follower.id = t1.id AND followee.id = :usr) 
    AND t1.active = true
ORDER BY t1.id

我的想法是我有两张桌子:

User table:
+------+--------+-------------+
|  id  | name   | last_name   |
+------+--------+-------------+
| 1    | Jhon   | Doe         |
| 2    | Jane   | Doe         |
| 3    | Alfred | Hitchcock   |
+------+--------+-------------+
Follows table:
+------+-------------+-------------+
|  id  | follower_id | followee_id |
+------+-------------+-------------+
| 1    | 1           | 3           |
| 2    | 3           | 2           |
| 3    | 2           | 1           |
+------+-------------+-------------+

我需要的是,例如,获取所有关注或被关注的用户的姓名和名字,例如,用户ID 1。

我发布的SQL查询就是这样做的,但我似乎无法在HQL中复制相同的行为。

第二次编辑: 我的简化域类是:

class User {
    String name
    String lastName
    ...
    static hasMany = [ follows: Follows ]
    static mappedBy = [ follows: 'follower' ]
}

和...

class Follows {
    User Followee
    ...
    static belongsTo = [follower: User]
}

2 个答案:

答案 0 :(得分:1)

在编写HQL查询时要记住的重要一点是域类加入(HQL处理域类,而不是表)完全依赖于域类关联。换句话说,关联实际上创建了(内部)连接,但是HQL允许您更改连接类型(LEFT OUTER,RIGHT OUTER和Cartesian)。请参阅我的from clause文章。

我尝试从您的HQL和表格描述中获取您的域类关联,但它并不匹配。但这是另一种方法。

域模型

域模型非常简单。那个&#39; sa User类包含一对多与自身的关联(但它不是自我加入,因为你会在力矩)。

class User {
    String name
    String lastName

    static hasMany = [followees: User]  
}

假设您有User个实例。

def user = User.get(1)

user.followees包含User 后跟 user

表架构

使用这样的域模型,表格看起来像这样:

用户表

+------+--------+-------------+
|  id  | name   | last_name   |
+------+--------+-------------+
| 1    | John   | Doe         |
| 2    | Jane   | Doe         |
| 3    | Alfred | Hitchcock   |
+------+--------+-------------+

user_followees表

+-----------+-------------------+
|  user_id  | followees_user_id |
+-----------+-------------------+
| 1         | 2                 |
| 3         | 1                 |
+-----------+-------------------+

所展示的数据表明:

  1. John Doe 关注 Jane Doe。
  2. Jane Doe 后面是 John Doe。
  3. Alfred Hitchcock 跟随 John Doe。
  4. John Doe 后面是 Alfred Hitchcock。
  5. 这个简单的一对多关联可用于建模双向关系,即跟随。使用两个一对多关联也可以完成相同的操作,这将简化查询,但会使数据维护变得复杂。使用此模型,双向以下关系将使用单个user.addToFollowee()user.removeFromFollowee()进行维护。

    查询

    使用我描述的域模型,您可以查询被关注者和关注者。给定user ...

    def followees = user.followees // <-- contains Jane Doe
    
    def followers = User.executeQuery 
        'SELECT u FROM User as u INNER JOIN u.followees as followee WHERE followee = :user',
        [user: user] // <-- contains Alfred Hithchcock
    
    def following = followees + followers
    

    请注意,GORM / Hibernate不支持SQL的 UNION 子句,因此您需要两个查询。有关GORM等效于where子句的更多详细信息,请参阅我的where clause文章。

    关注

    还可以使用 where 条件查询来获取关注者:

    def followers = User.where { followees.id == user.id }.list()
    def followers = User.withCriteria { followees { eq 'id', user.id } }
    

答案 1 :(得分:1)

仅仅是为了简单起见,因为我只是在阅读数据,所以我最终使用Grails接受的Groovy SQL,并且本身接受我原始帖子中包含的简单SQL查询(并且不需要匹配任何特定的域模型,在这种情况下对我来说很重要)

这里是JavaDoc的链接,我特意使用行(String sql,Map params)方法定义来查询de DB并返回我正在搜索的数据。

为了在Grails中使用groovy.sql.Sql,我建议将它作为bean添加到resources.groovy文件中:

beans = {

    groovySql(groovy.sql.Sql, ref('dataSource'))

}

然后将其注入您想要使用的地方:

class MyService {

    def groovySql
    ...

    def myMethod() {

        String query = "SELECT * FROM user WHERE ..."

        Map params = [param1: p1]

        List<GroovyRowResult> result = groovySql.rows(query, params)

        ...

    }

}

希望这可以帮助任何尝试执行纯SQL查询的人,而无需将其转换为HQL或Criteria。