查询的 Grails HQL 表示
Grails HQL representation of a query
我无法在 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 查询,但它无法 return 正确的数据:
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]
}
编写 HQL 查询时要记住的重要一点是 域 class 加入(HQL 处理域 classes,而不是 tables) 完全依赖于域 class 关联。换句话说,关联实际上创建了(内部)联接,但 HQL 允许您更改联接 type(LEFT OUTER、RIGHT OUTER 和 Cartesian)。请参阅我的 from clause 文章。
我试图从您的 HQL 和 table 描述中获取您的域 class 关联,但它不匹配。但这里有另一种方法。
领域模型
领域模型非常简单。有一个 User
class 包含与自身的 一对多 关联(但它不是自连接,稍后您会看到) .
class User {
String name
String lastName
static hasMany = [followees: User]
}
假设您有一个 User
实例。
def user = User.get(1)
user.followees
包含 User
, 后跟 user
。
Table 架构
有了这样的域模型,tables 看起来像这样:
用户table
+------+--------+-------------+
| id | name | last_name |
+------+--------+-------------+
| 1 | John | Doe |
| 2 | Jane | Doe |
| 3 | Alfred | Hitchcock |
+------+--------+-------------+
user_followees table
+-----------+-------------------+
| user_id | followees_user_id |
+-----------+-------------------+
| 1 | 2 |
| 3 | 1 |
+-----------+-------------------+
显示的数据表明:
- John Doe 关注 Jane Doe。
- Jane Doe 其次是 John Doe。
- Alfred Hitchcock 关注 John Doe。
- John Doe 其次是 Alfred Hitchcock。
这个简单的一对多 关联可以用来模拟被称为跟随 的双向关系。同样可以用两个一对多关联来完成,这将简化查询但使数据维护复杂化。使用此模型,双向 跟随 关系由单个 user.addToFollowee()
或 user.removeFromFollowee()
.
维护
正在查询
使用我描述的域模型,您可以查询 followees 和 followers。给定 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 或 criteria 查询来获取关注者:
def followers = User.where { followees.id == user.id }.list()
def followers = User.withCriteria { followees { eq 'id', user.id } }
只是为了简单起见,因为我只是在读取数据,所以我最终使用了 Groovy SQL,它被 Grails 接受并且它本身接受普通的 SQL 查询 I包含在我原来的 post 中(并且不需要匹配任何特定的域模型,在这种情况下对我来说是一大优势)
这里有一个link到JavaDoc,我专门用rows(String sql, Map params)方法定义来查询de DB和return数据我在找。
为了在 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 或标准的麻烦。
我无法在 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 查询,但它无法 return 正确的数据:
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]
}
编写 HQL 查询时要记住的重要一点是 域 class 加入(HQL 处理域 classes,而不是 tables) 完全依赖于域 class 关联。换句话说,关联实际上创建了(内部)联接,但 HQL 允许您更改联接 type(LEFT OUTER、RIGHT OUTER 和 Cartesian)。请参阅我的 from clause 文章。
我试图从您的 HQL 和 table 描述中获取您的域 class 关联,但它不匹配。但这里有另一种方法。
领域模型
领域模型非常简单。有一个 User
class 包含与自身的 一对多 关联(但它不是自连接,稍后您会看到) .
class User {
String name
String lastName
static hasMany = [followees: User]
}
假设您有一个 User
实例。
def user = User.get(1)
user.followees
包含 User
, 后跟 user
。
Table 架构
有了这样的域模型,tables 看起来像这样:
用户table
+------+--------+-------------+
| id | name | last_name |
+------+--------+-------------+
| 1 | John | Doe |
| 2 | Jane | Doe |
| 3 | Alfred | Hitchcock |
+------+--------+-------------+
user_followees table
+-----------+-------------------+
| user_id | followees_user_id |
+-----------+-------------------+
| 1 | 2 |
| 3 | 1 |
+-----------+-------------------+
显示的数据表明:
- John Doe 关注 Jane Doe。
- Jane Doe 其次是 John Doe。
- Alfred Hitchcock 关注 John Doe。
- John Doe 其次是 Alfred Hitchcock。
这个简单的一对多 关联可以用来模拟被称为跟随 的双向关系。同样可以用两个一对多关联来完成,这将简化查询但使数据维护复杂化。使用此模型,双向 跟随 关系由单个 user.addToFollowee()
或 user.removeFromFollowee()
.
正在查询
使用我描述的域模型,您可以查询 followees 和 followers。给定 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 或 criteria 查询来获取关注者:
def followers = User.where { followees.id == user.id }.list()
def followers = User.withCriteria { followees { eq 'id', user.id } }
只是为了简单起见,因为我只是在读取数据,所以我最终使用了 Groovy SQL,它被 Grails 接受并且它本身接受普通的 SQL 查询 I包含在我原来的 post 中(并且不需要匹配任何特定的域模型,在这种情况下对我来说是一大优势)
这里有一个link到JavaDoc,我专门用rows(String sql, Map params)方法定义来查询de DB和return数据我在找。
为了在 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 或标准的麻烦。