我正在编写一个带有grails的基本Web应用程序,使用带有MySQL和vaadin的hibernate,spring security和spring security acl插件,用于管理委员会,成员和委员会与成员之间的成员资格。所有CRUD都适用于成员和委员会,但是当我创建一个委员会成员对象时,它无法引用该类的成员字段来获取有关成员所涉及成员的信息。 这是我的课程:
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;
委员会成员引用的成员的任何领域均无法访问。我在这做错了什么?我做了很多研究,找不到这样的东西。帮助将非常感激。把头发拉过这个东西..
**更新
在服务层方法saveCommitteeMember()
中,我添加了一行println(cmem.member.firstName);
,并且在我的grails启动的终端中,它确实打印了我添加到委员会的成员的名字当我调用该函数时。
答案 0 :(得分:0)
JESUS。我终于弄明白了。好的,这就是发生了什么。 Hibernate执行findByFirstNameAndLastName()
,并且工作正常,但由于Grails默认为LAZY,它只返回对该Member对象的REFERENCE,而不是表中数据的对象表示。函数返回时会销毁此引用,并且委员会委员对象的成员字段指向任何内容。这特别棒,因为使用Vaadin插件,除非您明确尝试从@Transaction引用某些内容,否则不会获得LazyInitializationException - no session exists
或任何错误消息,因此执行def fname = cm.member.firstName
wasn'抛出所述异常,因为@Transaction被认为是成功的,我只是试图读取一个空值,除了发生错误的函数终止之外,没有任何错误消息。谈论一些严重的公牛#$&%!
无论如何,要修复这个荒谬的问题,请将此添加到您遇到空问题的对象
class CommitteeMember {
Member member
Committee committee
etc......
static mapping = {
member lazy: false
committee lazy: false
}
}
我真的希望有这样问题的其他人找到这篇文章。这花费了我很多时间在一些如此荒谬的事情上。在某些情况下,懒惰评估非常好。数据库操作,IMO,不是那种情况。无论如何,干杯。