用于在GORM中查询关联的子查询

时间:2015-02-27 12:24:42

标签: hibernate grails subquery gorm

我在GORM中有以下域名。

class Topic {
static hasMany = [resources: Resource, subscriptions: Subscription]
}

class Resource {
static belongsTo = [resourceOf: Topic]
}

class Subscription {
 static belongsTo = [subscriptionOf: Topic]
}

我无法使用标准/命名子查询找到运行子查询的语法。例如,如何使用标准在GORM中编写以下查询。

select topic.id, 
(select count(*) from Resource where resourceOf.id = topic.id) as numRes,
(select count(*) from Subscription where subscriptionOf.id = topic.id) as numSubs
from topic
where topic.id in (<My topic ids>)
group by topic.id;

这是非常基本的事情,但我无法找到相同的文档。

有谁知道如何使用GORM中的namedQueries来完成这项工作?

我的grails版本是2.4.4

3 个答案:

答案 0 :(得分:2)

您面临的问题是namedQueries不应与投影(摘要)一起使用。退一步,重置您对使用namedQueries时可以应该做什么的期望。

命名查询是创建标识较大集的子集的查询的便捷方式。可以将其视为逐步过滤数据。如果您查看文档中的示例,您将看到这些示例。这使namedQueries非常强大,但在特定用例中。

来自documentation

的示例
// get all old publications with more than 350 pages
// and the word 'Grails' in the title
def pubs = Publication.oldPublicationsLargerThan(350).findAllByTitleLike('%Grails%')

另一个例子可能是:

def divisions = Division.locatedIn('Sweden').havingNoOustandingBalance().havingMoreThanXEmployees(50).currentlyOpen().notOnFire()

在其他用例中,例如使用摘要和预测,它们不足。不是因为它们设计不佳或无能力,而是因为这不是他们的目的。

预测和摘要确实应该通过createCriteriaHQL本身创建。

虽然您可以通过攻击namedQueries进行预测和摘要,但您仍然需要与框架进行对抗。使用正确的工具来完成正确的工作,并完成更多工作。

<强>更新 但是,所有这些都说明了这个blog post解释了如何在命名查询(和标准)中使用投影。它应该让您更好地了解投影在GORM中的工作方式。

答案 1 :(得分:2)

您的查询是&#34;为我提供与给定主题列表及其各自的资源和订阅数量相匹配的主题。&#34;

(编辑反映意见) 我认为这可能适合你:

def myTopicIds = ['1', '2']  // search for ids 1 and 2
def criteria = Topic.createCriteria()
def results = criteria.list() {
    'in'('id', myTopicIds)  // restrict results to only those matching your given ids
    projections {
        property("id")
        resources {
            countDistinct('id')   
        }
        subscriptions {
            countDistinct('id')   
        }
       groupProperty('id')
    }
}.collect {
        [
            topicId: it[0],
            numRes: it[1],
            numSubs: it[2]
        ]
    }

collect会更改结果集合,并允许您将结果作为地图引用,其中每个项目都有3个显示名称的键,否则您只需要引用无名数组项。

答案 2 :(得分:1)

为什么不尝试这样的事情......

def exampleSubQuery = new grails.gorm.DetachedCriteria(Resource).build {
   // your criteria here, "normal" GORM
   // and the same for Subscription 
}

...然后在主查询中附加此子查询。

看看这个,可能会对你有所帮助:Can't get "count" and "groupBy" with Grails DetachedCriteria