似乎这个问题被问了一遍又一遍,我仍然没有找到一个答案来解决我的。下面是一个域模型。我需要为每一个新创建或更新Sec用户确保它有一个配置文件,如果没有,然后创建一个新的并分配给它。
配置文件同样需要-每次保存期间检查它是否有工作空间,如果没有则创建一个。这样做是为了确保所有Sec用户至少有一个工作区。除了所有者自己,一个工作区可能有不同的贡献者。
当我试图保存Sec User时,我总是得到:
object references an unsaved transient instance save the transient instance before flushing
总的来说,我确实理解问题的本质。在构造函数中传递的实例没有持久化,因此没有id。我仍然不知道如何强制这3个插入成为单个事务的一部分,并正确处理引用。
class SecUser implements Serializable {
String email
static hasOne = [profile: Profile]
def beforeValidate() {
if (profile == null) {
profile = new Profile(secUser: this)
}
profile.validate()
}
}
class Profile {
static belongsTo = [secUser: SecUser]
static hasMany = [workspaces: Workspace]
static constraints = {
workspaces minSize: 1
}
def beforeValidate() {
if (workspaces == null || workspaces.isEmpty()) {
def workspace = new Workspace(owner: this).save()
workspaces = [workspace]
}
}
}
class Workspace {
String title = "Workspace ${10000 + new Random().nextInt(89999)}"
static hasOne = [owner: Profile]
static belongsTo = Profile
static hasMany = [contributors: Profile]
}
更新1
我已经替换了
workspaces = [workspace]
this.addToWorkspaces(workspace)
现在我得到了这个:
错误spi。SqlExceptionHelper—引用完整性约束违规:"FK_MYFCABJIQ83AG2CLBDF61MPA5: PUBLIC。PROFILE_WORKSPACES外键(workspace_id)引用public.workspace (id) (0)";SQL语句:insert into profile_workspace (profile_id, owner_id)值(?, ?) [23506-176].
生成了一个新的连接表,它有3列。我看到它试图做错误的插入。应该插入owner_id, workspace_id (profile_id应为空)
当我处理涉及多个域对象的业务事务时,我创建了一个Grails服务。使用服务可以简化域单元测试,还有助于描述代码要完成的任务。可以把它看作事务脚本设计模式(Gang of Four)。
你的服务可以有create()和update()方法,然后你可以从控制器调用它们。然后,您的服务将根据需要连接SecUser、Profile和Workspace。