【问题标题】:Hibernate cascade + composite id's issueHibernate级联+复合ID的问题
【发布时间】:2011-10-18 15:32:23
【问题描述】:

我目前正在学习 Hibernate,我偶然发现了这个问题: 我定义了 3 个实体:用户、模块、权限。 user 和 module 都与 Permission 是一对多的关系,所以 Permission 的复合 id 由 idUser 和 idModule 组成。用户类有一个属性,它是一组权限,并用@OneToMany、cascade=CascadeType.ALL 等适当地注释。

现在,我使用 MyEclipse 的逆向工程功能生成了这些类。权限的 id 被创建为具有 idUser 和 idModule 属性的单独类。我以为我可以创建一个用户,给它添加一些新的权限,这样保存用户就会级联操作,权限会自动保存。这是真的,只是该操作会导致异常。我运行以下代码:

Permission p = new Permission();
p.setId(new PermissionId(null, module.getId());
user.getPermissions().add(p);
session.save(user);

我遇到的问题是,即使正确生成了 SQL(首先保存用户,然后保存权限),我从数据库驱动程序 (Firebird) 收到一个错误,指出它无法为idUser,这是真的,但hibernate不应该将新创建的用户id传递给第二个查询吗?

这个特殊场景对我来说感觉非常违反直觉,因为我倾向于将 null id 传递给 Permission 对象,因为它是新的并且我希望创建它,但另一方面,我必须设置 idModule属性,因为模块已经存在,所以我真的不明白这样的操作应该如何工作。

有谁知道我做错了什么?谢谢

【问题讨论】:

    标签: java database hibernate firebird myeclipse


    【解决方案1】:

    您需要指定 cascade action 以在您保存带有附加瞬态(表示尚未保存)PermissionUser 时执行 Hibernate。

    顺便说一句,您可能要考虑对Permission 对象使用不同的ID 策略,例如生成的ID 值——数据库中permission 行的主键如何包含空值?

    【讨论】:

    • 谢谢。但是 Cascade.ALL 不是对所有动作都有效吗? Permission 对象不能有空值。问题是我必须将其 idUser 属性设置为 null,因为尚未创建用户。我认为一旦用户对象被持久化,级联操作就会将此值传递给 Permission 对象。就像我说的那样,该操作正在生成两个查询(插入用户,插入权限),只是插入权限的部分无权访问新创建的用户 ID。
    • 如果您打算生成 Permission id,则不应将其设置为非空值。 Hibernate 需要知道它是否应该为实体生成一个 ID——默认的做法是为 ID 使用未保存的 null 值——参见the manual 的这一部分。但请注意,它指的是使用复合 ID 执行此操作的困难。最后,我对使用生成值(例如自动增量)的建议是针对 Permission ID,而不是 Permission。
    • 问题在于,在这种情况下,由于 id 是复合的,id 的一部分是新的(用户 id),而另一部分不是(模块 id 来自一个已经存在)。所以我必须至少手动设置 id 的模块部分,否则它不会正确链接到模块实体。但是,如果我理解正确,我必须将整个 id 属性保留为空,否则它将无法工作?
    • 谢谢,手册的那部分没有显示如何使用复合 ID 来完成。我开始认为在这种情况下根本不支持这一点。我想我要手动插入 Permission 对象。
    猜你喜欢
    • 2011-12-31
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多