【发布时间】:2015-08-13 05:21:49
【问题描述】:
似乎这个问题被一遍又一遍地问到我仍然找不到解决我的问题的答案。我在下面有一个域模型。我需要为每个新创建或更新的 Sec 用户确保它有一个配置文件,如果没有,则创建一个新的并分配给它。
配置文件的要求相同 - 每次保存期间检查它是否有工作区,如果没有,则创建一个。这样做是为了确保所有 Sec User-s 至少有一个工作空间。除了所有者本人之外,工作空间可能有不同的贡献者。
当我尝试保存 Sec 用户时,我总是得到:
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)
现在我明白了:
ERROR spi.SqlExceptionHelper - 参照完整性约束 违规:“FK_MYFCABJIQ83AG2CLBDF61MPA5:PUBLIC.PROFILE_WORKSPACES FOREIGN KEY(WORKSPACE_ID) REFERENCES PUBLIC.WORKSPACE(ID) (0)"; SQL 语句:插入 profile_workspaces (profile_id, owner_id) 值 (?, ?) [23506-176]。
已生成一个包含 3 列的新连接表。我看到它试图进行错误的插入。它应该插入到 owner_id、workspace_id(profile_id 应该为空)
【问题讨论】:
-
您应该调用
this.addToWorkspaces(workspace)而不是workspaces = [workspace]。您还应该在验证后保存配置文件。 -
好的,现在我明白了:错误 spi.SqlExceptionHelper - 违反参照完整性约束:“FK_MYFCABJIQ83AG2CLBDF61MPA5: PUBLIC.PROFILE_WORKSPACES FOREIGN KEY(WORKSPACE_ID) REFERENCES PUBLIC.WORKSPACE(ID) (0)”; SQL 语句:插入 profile_workspaces (profile_id, owner_id) 值 (?, ?) [23506-176]。已生成一个新的连接表,它有 3 列。我看到它试图进行错误的插入。它应该插入到 owner_id、workspace_id @defectus
-
Profile 和 Workspace 之间有两种关联:多对多和一对一。多对多应该产生一个连接表,在您的情况下,它看起来像名为 profile_workspaces。 profile_workspaces 应该只有两列:profile_id 和workspace_id。我认为您在 Profile 和 Workspace 之间的一对一操作不起作用。您应该在拥有方(例如个人资料)上有一个 hasOne(),在拥有/从属方(例如工作区)上有一个属性(例如所有者)或 belongsTo()。就像 SecUser 和 Profile 之间的一对一一样。
标签: hibernate grails grails-orm