grails/hibernate 条件如何获取至少有一个 child 满足条件的所有行
grails/hibernate criteria how to get all rows that have at least one child meeting condition
我的理解是嵌套子查询过滤 children。不是 parent。也就是说
Parent.withCriteria{
children{
gt('age', 5)
}
}
会 return 所有 Parents,但只有那些 parent 的 children 超过 5.
以示例为例,我想要的是仅获取至少一个child超过5岁的parent,并获取所有child ren parents.
我需要这个等价物的查询是...
SeasonDetails.withCriteria{
not{
clubHistory{
club{
eq('division',division);
}
}
}
}
我只获得与特定俱乐部无关的赛季详细信息。
HQL 的工作方式不同吗?也许我需要走那条路
string query="""select new map(p as parent, c as children) from Parent p left join p.children c where c.age > :ageLimit"""
def inputParams=[:]
inputParams.ageLimit = 5
def results = Parent.executeCriteria(query,inputParams)
result?.each { r ->
println "${r?.parent?.id} is parent id "
r?.children?.eachWithIndex { c, i ->
println "${c.id} ${c.age} is iteration ${i}"
}
}
上面应该是 HQL 中的查询来执行您需要的操作,目前它是 returning 地图中的整个 objects。这可能很昂贵并且会导致不必要的查找,(在上面迭代时必须重新连接并再次获取它)
你可以做什么,而不是它捕获你需要的所有东西,并使用 groupBy 来准确地得到你需要的东西,所以 ..
string query="""select new map(p.name as parentName, p.id as parentId
, c.id as childId, c.age as childAge, c.name as childName) from Parent p
left join p.children c where c.age > :ageLimit"""
现在应该 return 如果 ids 名称和年龄是您想要的,那么这应该是您需要的所有内容的简单列表。现在你每个 parent 的数量是 children 所以如果 parent 1 有 6 children 它重复两次(正如你在上面的迭代中看到的那样)
你可以使用 groupBy
def finalList = results.groupBy{it.parentId}
现在这会将上面的列表更改为每个 parent 组,其中包含每个 child 作为列表迭代..
hql 也有 group by 你可能需要尝试一下,看看什么最适合你。
查询 1 和查询 2 之间的主要区别在于查询 1 在迭代时仍将与数据库交互以 return 实际 objects。在 query2 中,您 return 将所有结果作为平面迭代处理,不再连接到实际的真实数据库 objects。如果您启用 SQL 调试,您将看到通过第二种方法进行的工作减少了多少。
我的理解是嵌套子查询过滤 children。不是 parent。也就是说
Parent.withCriteria{
children{
gt('age', 5)
}
}
会 return 所有 Parents,但只有那些 parent 的 children 超过 5.
以示例为例,我想要的是仅获取至少一个child超过5岁的parent,并获取所有child ren parents.
我需要这个等价物的查询是...
SeasonDetails.withCriteria{
not{
clubHistory{
club{
eq('division',division);
}
}
}
}
我只获得与特定俱乐部无关的赛季详细信息。
HQL 的工作方式不同吗?也许我需要走那条路
string query="""select new map(p as parent, c as children) from Parent p left join p.children c where c.age > :ageLimit"""
def inputParams=[:]
inputParams.ageLimit = 5
def results = Parent.executeCriteria(query,inputParams)
result?.each { r ->
println "${r?.parent?.id} is parent id "
r?.children?.eachWithIndex { c, i ->
println "${c.id} ${c.age} is iteration ${i}"
}
}
上面应该是 HQL 中的查询来执行您需要的操作,目前它是 returning 地图中的整个 objects。这可能很昂贵并且会导致不必要的查找,(在上面迭代时必须重新连接并再次获取它)
你可以做什么,而不是它捕获你需要的所有东西,并使用 groupBy 来准确地得到你需要的东西,所以 ..
string query="""select new map(p.name as parentName, p.id as parentId
, c.id as childId, c.age as childAge, c.name as childName) from Parent p
left join p.children c where c.age > :ageLimit"""
现在应该 return 如果 ids 名称和年龄是您想要的,那么这应该是您需要的所有内容的简单列表。现在你每个 parent 的数量是 children 所以如果 parent 1 有 6 children 它重复两次(正如你在上面的迭代中看到的那样)
你可以使用 groupBy
def finalList = results.groupBy{it.parentId}
现在这会将上面的列表更改为每个 parent 组,其中包含每个 child 作为列表迭代..
hql 也有 group by 你可能需要尝试一下,看看什么最适合你。
查询 1 和查询 2 之间的主要区别在于查询 1 在迭代时仍将与数据库交互以 return 实际 objects。在 query2 中,您 return 将所有结果作为平面迭代处理,不再连接到实际的真实数据库 objects。如果您启用 SQL 调试,您将看到通过第二种方法进行的工作减少了多少。