Grails - 非空属性引用空值或瞬态值

Posted

技术标签:

【中文标题】Grails - 非空属性引用空值或瞬态值【英文标题】:Grails - not-null property references a null or transient value 【发布时间】:2011-12-23 21:32:41 【问题描述】:

我有一些基本的 grails 域对象:

任务 用户

最近,我希望能够将任务分配给多个用户。所以我将这段代码添加到 Task.groovy 类中:

static hasMany = [users: User]

static mapping = 
    users joinTable: [name: 'task_user', column: 'user_id', key: 'task_id']

因此,现在可以使用连接表将任务分配给多个用户 - 连接任务和用户表。现在,当我创建一个新任务时,它给了我错误消息:

“非空属性引用空值或临时值:blah.User.address”

在生成的连接表“task_user”中,它只需要来自用户对象的 user_id,所以我不明白为什么它抱怨其他用户字段为空。用户对象将始终存在于数据库中。我不想为了创建新任务而完全加载每个用户。我很确定它与级联有关。

我想要的行为是,如果删除任务,则应删除 task_user 连接表中的关联条目。我“从不”希望用户对象因保存任务而被更新/删除。我不确定如何继续。

【问题讨论】:

你能发布一些产生错误的代码吗?这将有助于给出更好的答案。我的第一个想法是您引用的 User 对象不是 User 的实例化版本(这意味着它只有一个 id 集,在这种情况下您会收到这样的错误) 【参考方案1】:

修复

您需要使用 User.load(id) 来获取对用户对象的引用。 load 不像 get 不会命中数据库——它只是创建一个代理,可以用来代替 User 对象。只要只访问 id 属性 - 就不会访问 db。

您看到的错误的解释

在您的代码中,您创建了一个未连接到休眠的新用户对象(瞬态)。要将其连接到休眠状态,您需要保存它或添加 belongs_to 属性 - 这两者都将尝试更新用户表中的行,并将每个字段设置为空。如果它是您正在创建的新用户对象并希望自动保存它,则需要设置 belongs_to(~ 级联)。

【讨论】:

还有一个问题,根据我在原始帖子中构建映射的方式,如果我的临时用户集合中唯一的非空字段是“id”,然后我加载正如我在上一条评论中所说的用户并最终保存任务:myTask.save(failOnError:true);由于级联,我是否会有任何用户被自动更新的危险?还是只有当我在 User 对象中添加belongs_to 时?级联规则有点复杂。谢谢。 关于第一个问题 - 您从哪里获得任务。如果它是一个表单输入——我认为有一种方法可以让 grails 自动执行它——将表单中的 id 绑定到 User.load。否则,最好将其作为单独的用户 ID 集合,而不是将其设置为 Task.users。在第二个问题上-不,如果您加载对象,则它不可能自动更新-它会被更新的唯一情况是您设置了一个属性-在这种情况下,对象将首先从数据库中初始化.【参考方案2】:

您最近是否修改了对 User 表的约束?我以前见过这些错误,通常是当我在模式已经生成后使属性不可为空时......我猜测表中是否已经有一个空值用于修改为不可为空的属性的模式-update 静默失败,最终会出现这样的错误。

【讨论】:

以上是关于Grails - 非空属性引用空值或瞬态值的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate - 非空属性引用空值或瞬态值

非空属性为持久值引用空值或瞬态值

Spring 和 Hibernate 错误——非空属性引用空值或瞬态值:com.tharaka.model.Employee.designation

非空属性引用瞬态值 - 瞬态实例必须在当前操作之前保存

插入时 NHibernate 组件非空属性

Grails Gorm:Object引用未保存的瞬态实例