Hibernate Grails中的多对多关系

Hibernate Grails中的多对多关系,hibernate,grails,orm,gorm,grails-plugin,Hibernate,Grails,Orm,Gorm,Grails Plugin,我正在使用hibernate w/MySQL和vaadin、spring security和spring security acl插件编写一个带有grails的基本web应用程序,这些插件用于管理委员会、成员以及委员会和成员之间的成员身份。所有CRUD都适用于成员和委员会,但当我创建CommitteeMember对象时,它很难引用类的成员字段来获取成员身份中涉及的成员的信息。 以下是我的课程: class Committee { String name String descri

我正在使用hibernate w/MySQL和vaadin、spring security和spring security acl插件编写一个带有grails的基本web应用程序,这些插件用于管理委员会、成员以及委员会和成员之间的成员身份。所有CRUD都适用于成员和委员会,但当我创建CommitteeMember对象时,它很难引用类的成员字段来获取成员身份中涉及的成员的信息。 以下是我的课程:

class Committee {
    String name
    String description
    String bylaws
    static hasMany = [members: CommitteeMember]
    static constraints = {
        name blank: false, nullable: false, matches: "[a-zA-Z0-9 ]*", unique: true
        description blank: false, nullable: false, matches: "[a-zA-Z0-9 ]*"
        bylaws blank: false, nullable: false, matches: "[a-zA-Z0-9 ]*"
   }
}

class Member {
    String firstName
    String middleName
    String lastName
    String address
    String phone

    static hasMany = [committees: CommitteeMember]
    static constraints = {
        firstName blank: false, nullable: false, matches: "[a-zA-Z]*"
        middleName blank: false, nullable: false, matches: "[a-zA-Z]*"
        lastName blank: false, nullable: false, matches: "[a-zA-Z]*"
        address blank: false, nullable: false, matches: "[0-9a-zA-Z ]*"
        phone blank: false, nullable: false, minSize: 10, maxSize: 10, matches: "[0-9]*"
    }
}

class CommitteeMember {

    Member member
    Committee committee
    Date startDate
    Date endDate
    String title
    Date created = new Date()
    Date updated = new Date()

    static constraints = {
        startDate blank: false, nullable: false, format: 'mm/dd/yyyy'
        endDate blank: false, nullable: false, format: 'mm/dd/yyyy'
        title blank: false, nullable: false, matches: "[a-zA-Z0-9 ]*"
        created blank: false, nullable: false, editable: false, display: false
        updated blank: false, nullable: false, editable: false, display: false
    }

}
以及服务层添加这些类的方法:

@Transactional
def saveCommittee(name, desc, bylaws) {
    new Committee(name: name, description: desc, bylaws: bylaws).save(flush: true);
}

@Transactional
def saveMember(fname, mname, lname, address, phone) {
    new Member(firstName: fname, middleName: mname, lastName: lname,
                 address: address, phone: phone).save(flush: true);
}

@Transactional
def saveCommitteeMember(cname, lname, fname, title, start, end) {
    def cmem = new CommitteeMember(title: title, startDate: start, endDate: end);
    cmem.member = Member.findByLastNameAndFirstName(lname, fname);
    cmem.committee = Committee.findByName(cname);
    cmem.save(flush: true);
}
创建这些类是可行的,它们存储在数据库中。我的更新和删除方法对成员和委员会非常有效。但是,当我试着

//this works
def cm = CommitteeMember.get(1);
def title = cm.title;

//this does not
def firstName = cm.member.firstName;
委员会成员引用的成员字段均不可访问。我做错了什么?我做了很多研究,找不到像这样的东西。非常感谢您的帮助。为了这件事把我的头发拔出来

**更新


在服务层方法
savecommitteember()
中,我添加了一行
println(cmem.member.firstName),并且在我的grails启动的终端中,它确实打印了我在调用函数时添加到委员会的成员的名字。

。我终于明白了。好的,这就是发生的事情。Hibernate确实
findByFirstNameAndLastName()
,这很好,但由于grails在默认情况下是惰性的,因此它只返回对该成员对象的引用,而不返回表中数据的对象表示形式。当函数返回时,此引用将被销毁,CommitteeMember对象的成员字段将不指向任何内容。这特别好,因为使用Vaadin插件,您不会得到
LazyInitializationException-不存在会话
或任何错误消息,除非您显式尝试引用@Transaction中的某个内容,因此执行
def fname=cm.member。firstName
不会引发所述异常,因为@Transaction被认为是成功的,而我只是尝试读取一个空值,这不会导致任何错误消息,除了终止发生错误的函数。谈论一些严肃的牛市

无论如何,要解决这个荒谬的问题,请将其添加到存在空问题的对象中

class CommitteeMember {

    Member member
    Committee committee
    etc......

    static mapping = {
        member lazy: false
        committee lazy: false
    }

}

我真的希望任何有类似问题的人都能找到这篇文章。这让我花了很多时间在这么荒谬的事情上。在某些情况下,惰性评估非常好。数据库操作,IMO,不是那种情况。无论如何,干杯。

您是否检查了
成员.findbylastname和firstname(lname,fname)
是否返回值?添加一些日志以检查其未设置空/空值。是否有理由编写自己的服务层来持久化该值?Grails脚手架应该自动为您完成这项工作。您是否尝试生成控制器以便在生成的代码顶部添加安全ACL?是的,应该是。这就是我如何定位要删除的成员的方法。
delete()
。我认为如果CommitteeMember返回null,它根本就不会
save()
committeeMber。我编写服务层是因为Vaadin插件使它成为一个框架或控制器。不是我选择使用Vaadin..:(