2011-10-18 66 views
0

我目前在学习Hibernate,我偶然发现了这个问题: 我已经定义了3个实体:User,Module,Permission。用户和模块都与Permission具有一对多关系,因此Permission的复合ID由idUser和idModule组成。用户类的属性是一组权限,并且使用@OneToMany,cascade = CascadeType.ALL等进行适当注释。Hibernate级联+复合id的问题

现在,我使用MyEclipse的逆向工程功能生成了类。权限的id被创建为一个具有idUser和idModule属性的独立类。我想我可以创建一个用户,为它添加一些新的权限,从而保存用户级联操作,权限将被自动保存。除了操作导致异常之外,这是正确的。我运行下面的代码:

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

我的问题是,即使正在正确生成SQL(先保存用户,然后许可),我从其中规定的数据库驱动程序(火鸟)得到一个错误它不能为idUser插入一个空值,这是真的,但不应该hibernate传递新创建的用户id到第二个查询?

这个特殊的场景对我来说感觉非常不直观,因为我倾向于将一个空ID传递给Permission对象,因为它是新的,我希望它被创建,但另一方面,我必须设置idModule属性,因为模块已经存在,所以我不太了解像这样的操作应该如何工作。

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

回答

0

您需要指定一个cascade action让Hibernate在保存User时附带一个瞬态(意味着尚未保存)Permission

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

+0

谢谢。但Cascade.ALL并不适用于所有操作? Permission对象不能有空值。问题是我必须将其idUser属性设置为null,因为用户尚未创建。我认为一旦用户对象被持久化,级联操作会将此值传递给Permission对象。就像我说的那样,该操作会生成两个查询(插入用户,插入权限),只是插入权限的部分无法访问新创建的用户标识。 – JayPea

+0

如果您打算生成权限标识,则不应将其设置为非空值。 Hibernate需要知道它是否应该为实体生成一个ID - 而且默认的做法是使用ID未使用的空值 - 参见[手册]的这部分(http:// docs。 jboss.org/hibernate/core/3.6/reference/en-US/html/example-parentchild.html#example-parentchild-update)。请注意,它指的是使用复合ID执行此操作时遇到的困难。最后,我关于使用生成的值(如自动增量)的建议是针对权限ID而不是权限。 –

+0

问题是,在这种情况下,由于id是复合的,id的一部分是新的(用户id),另一部分不是(模块id来自已经存在的模块对象)。所以我必须至少手动设置ID的模块部分,否则它不会正确链接到模块实体。但是,如果我理解正确,我必须将整个id属性留空,否则它不会工作? – JayPea