Grails,左外连接

时间:2011-06-28 06:55:01

标签: grails groovy left-join

我有两个域类用户和项目,如下面的

Users{
    String firstName
    String lastName
    String emailAddress
    static hasMany = [projects:Projects]
}



class Projects {
    String projectName
    String description
    Users projectLead
    Date completionDate
    static belongsTo = Users
}

此处,completionDate == null表示项目尚未完成。

现在我想向每个用户发送一封关于他们不完整项目的电子邮件提醒,如何编写查询以检索每个用户的不完整项目?

我正在考虑以下行,但仍然无法继续。为了发送电子邮件,我需要用户emailid,所有不完整的项目及其名称

def users = Users.list()
       for(user in users){
           user.projects.find{it.completionDate==null}
       }

在这种情况下是否可以使用createCriteria?

2 个答案:

答案 0 :(得分:4)

我认为这应该有效:

def usersAndIncompleteProjects = Users.withCriteria {
    projects {
        isNull( completionDate )
    }
}

这应该只返回具有不完整项目的用户,并且每个projects的{​​{1}}属性仅包含不完整的项目。如果您希望用户加载所有项目,我believe you need to use an alias


测试...

鉴于User类:

User

项目类:

package criteriatest

class User {
    String name

    static hasMany = [ projects: Project ]
}

此集成测试通过(希望断言解释它)

package criteriatest

class Project {
    String name
    Date completionDate

    static belongsTo = User

    static constraints = {
        completionDate( nullable:true )
    }
}

(这是条件查询在此实例中执行的sql):

package criteriatest

import grails.test.*

class UserTests extends GroovyTestCase {
    protected void setUp() {
        super.setUp()
        User.withSession { session ->
            def tim = new User( name:'tim' )
            def dave = new User( name:'dave' )

            [ tim, dave ]*.save()

            def project1 = new Project( name:'project 1', completionDate:null )
            def project2 = new Project( name:'project 2', completionDate:new Date() )

            tim.addToProjects project1
            tim.addToProjects project2

            [ project1, project2 ]*.save()

            session.flush()
            session.clear()
        }
    }

    protected void tearDown() {
        super.tearDown()
    }

    void testQuery() {
        def usersAndIncompleteProjects = User.withCriteria {
            projects {
                isNull 'completionDate'
            }
            order 'name', 'asc'
        }

        // We get two users back (users with no projects get returned as well)
        assert usersAndIncompleteProjects.size() == 2

        // First user (dave) has no projects
        assert usersAndIncompleteProjects[0].projects.size() == 0

        // Second user (tim) has one project (with a null completionDate)
        assert usersAndIncompleteProjects[1].projects.size() == 1

        // Check it's the right project
        assert usersAndIncompleteProjects[1].projects*.name == [ 'project 1' ]
    }
}

答案 1 :(得分:3)

我不确定此问题是否需要左连接,除非您要包含具有空用户的项目。为什么不选择具有空完成日期的所有项目并加入对用户?

在HQL中,它看起来像这样:

Projects.executeQuery('from Projects p join p.projectLead u where p.completionDate is null')

您可以在条件查询中执行类似操作:

Projects.withCriteria {
    isNull('completionDate')
    join('projectLead')
}