实体之间关系的标准 - Grails

时间:2016-05-16 23:17:28

标签: grails criteria grails-2.0 hibernate-criteria grails-domain-class

我有一个包含以下实体的应用:

主题:

class Topic {

   UUID id
   String description
   String name
   boolean visibility = true

   // Relation
   static hasMany = [tests:Test]
   ...
}

测试

class Test {

    UUID id
    boolean active = true
    String description
    ...

    static hasMany = [evaluationsTest: Evaluation]
    static belongsTo = [topic: Topic, catalog: Catalog]
}

当我向用户显示所有可见主题时,我请求查询:

def visibleTopics = Topic.findAllByVisibility(true, [sort:"name", order:"asc"])

此查询返回我的示例:[['English'], ['Spanish']]。然后,我可以向用户显示有关每个主题的完整信息。

但我还想向用户表明每个可见主题中的活动测试次数。

例如:

English topic has 2 active test.
Spanish topic has a total of 2 test. One is active and the other is not.
German topic has not any active test.

然后我需要一个结果为def activeTotalEachTopic = [[2],[1],[0]]的查询,我可以将activeTotalEachTopic变量传递给视图(.gsp)。

解决方案:

从我可以获得所有可见主题的第一个查询中,我得到了活动测试的数量。

def visibleTopics = Topic.findAllByVisibility(true, [sort:"name", order:"asc"])

def numberActiveTest = []

activeTopics.each { topic ->
    def result = Test.findAllByTopicAndActive(topic, true).size()
    numberActiveTest.push(result)
}

我将这两个变量传递给视图。

render view: 'home', model: [activeTopics: activeTopics, numberActiveTest: numberActiveTest]

1 个答案:

答案 0 :(得分:0)

您缺少的是分组,以便您获得每组的计数,而不是总计数。

您还需要将连接类型从默认内部联接更改为外部联接,以使没有活动测试的主题返回0.但是,这样做的副作用是它会更改关联属性的引用方式到联接创建的别名。像这样:

import static org.hibernate.sql.JoinType.*

def activeTotalEachTopic =  Topic.createCriteria().list() {
    createAlias('tests', 't', LEFT_OUTER_JOIN)

    eq 'visibility', true

    or {
        eq 't.active', true
        isNull 't.id'
    }

    projections {
       groupProperty 'name'
       count()
    }        
    order ("name", "asc")
}

现在,要解决的另一个问题是,由于分组:[['English', 2],['Spanish', 1],['German', 0]],输出将是这样的。所以你可以做的是收集每个子列表中的第二项:

activeTotalEachTopic*.getAt(1)

// Which is the equivalent of...

activeTotalEachTopic.collect { it[1] }