我们有以下实体关系。用户是父实体.DistrictUserDetail是子实体。
@Entity
@Table(name="USERS")
public class User implements Serializable {
@Id
@Column(name="ID", nullable=false)
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
@OneToOne(cascade= {CascadeType.ALL})
@PrimaryKeyJoinColumn(name="ID", referencedColumnName="USER_ID")
public DistrictUserDetail districtUserDetail;
... other properties..
这是父实体。 子实体主键是User实体的外键,我们将其关键属性定义为:
@Entity
@Table(name="DISTRICT_USER_DETAIL")
public class DistrictUserDetail implements Serializable{
@Id
@Column(name="USER_ID")
@GeneratedValue(generator="foreign")
@GenericGenerator(name="foreign", strategy = "foreign",
parameters={@Parameter(name="property",value="user")})
protected String userId;
@OneToOne(mappedBy="districtUserDetail")
User user;
... other properties
因此,当我们创建一个新用户,并创建一个新的DistrictUser,并将DistrictUser设置为User并保存用户时,我们希望保存用户,并且由于cascadeAll,还保存了DistrictUser。
这是我们的测试:
public void testSaveUserWithDistrictUserDetails() throws Exception {
User user = new User();
user.setFirstName("John");
user.setLastName("Doe");
user.setUserName("U11111");
DistrictUserDetail userDetail = new DistrictUserDetail();
userDetail.setIsLoginAllowed(Boolean.TRUE);
userDetail.setIsSuperintendent(Boolean.TRUE);
user.setDistrictUserDetail(userDetail);
User newUser = dao.save(user);
assertTrue(newUser!=null);
assertTrue(newUser.getId()!=null);
}
但我们遇到以下hibernate异常:
Caused by: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: user
at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:44)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:99)
at org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:315)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:283)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:238)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:688)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:670)
at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:269)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:217)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:170)
at org.hibernate.engine.Cascade.cascade(Cascade.java:131)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
at org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:352)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:283)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:238)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:678)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:662)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:666)
at org.springframework.orm.hibernate3.HibernateTemplate$23.doInHibernate(HibernateTemplate.java:817)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
... 49 more
如果User实体可以调用DistrictUserDetail的保存,那么为什么DistrictUserDetail不能看到父User(及其新id)并使用它来保存它。
我们使用的是hibernate版本:3.2.7.ga 底层数据库是:MySQL
任何帮助将不胜感激。 感谢
答案 0 :(得分:1)
userDeatil.user
是null
,这是异常抱怨的内容。
我建议删除属性而不是双向关系。否则,user.setDistrictUserDetail()
还需要设置user
属性。
答案 1 :(得分:1)
您应该将OneToOne的可选属性设置为false,如下所示:
@OneToOne(mappedBy="districtUserDetail", optional = false)
User user;
此外,您当然应将DistrictUserDetail.user设置为非空实体。