例如,我是父类Cafee:
class Cafee {
String name
static hasMany = [
admin: Person
]
}
和一个子类人员:
class Person {
String name
static belongsTo = [cafee: Cafee]
}
我使用以下方式为Cafee做了一些记录:
def user = new Person(name: "Andrew")
def a = new Cafee(name: "Tarelka")
.addToAdmin(user)
.save()
将子项添加到父项可以正常工作,但是当我尝试单独创建Person-instance时,例如:
def visitor = new Person(username: 'testerUser', password:'password', firstName:'Иван', lastName:'Иванов', email:'ivanov@gmail.com', isAdminCafee: false)
visitor.save(flush:true)
我收到错误:
ERROR context.GrailsContextLoaderListener - Error initializing the application: object references an unsaved transient instance - save the transient instance before flushing: restorator.auth.Person; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: restorator.auth.Person
Message: object references an unsaved transient instance - save the transient instance before flushing: restorator.auth.Person; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: restorator.auth.Person
如何解决?
答案 0 :(得分:2)
这里有两件事情并不完全明显。一种是这种形式的belongsTo
static belongsTo = [cafee: Cafee]
与相比,是双向的
static belongsTo = [Cafee]
是不定向的;在两种变体中,Cafee
可以通过其Person
集合访问其关联的admin
实例,但使用第二种语法,Person
没有直接的方法可以知道Cafee
hasMany
它与。
像你一样声明Set
会在班级中创建Person
个hasMany
,其名称是您在admin
地图中使用的密钥,在此情况1}};好像你已经添加了
Set<Person> admin
但你不应该因为它是多余的 - AST转换将该属性添加到字节码。
同样,在声明时
static belongsTo = [cafee: Cafee]
将类型Cafee
的字段cafee
添加到类中。就好像你添加了
Cafee cafee
但请再次注意,请不要手动添加,只要注意它们就在那里。
所以问题是默认情况下持久属性不是null,除非你用nullable: true
覆盖,所以如果你打印出Person
个实例的错误,你会看到至少有一个抱怨不可为空的cafee
属性为null。这与addToAdmin
一起使用,因为该方法做了很多。如果将set实例化为新的Set
接口实现(可能只是HashSet
),如果它为null(这应该只在域类实例是新的时才会发生;持久集永远不会为null,只是清空或包含项目),然后将Person
添加到集合中,最后如果关系是双向的,则会将Person
上的反向引用设置为拥有Cafee
。
所以你所缺少的是手动设置Cafee
,作为地图构造函数的一部分
user = new Person(cafee: a, username: 'testerUser', ...)
工作流程中的或更高版本(但在验证或保存之前)
user = new Person(username: 'testerUser', ...)
...
user.cafee = a
...
user.save()