2013-02-26 66 views
2

我对双向OneToOne关系有些困惑,双向关系可能不是可选的。我使用JPA2与Hibernate:非可选双向OneToOne关系

@Entity 
@Table(name = "city") 
public class City { 

@Id 
@GeneratedValue 
@Column 
public Long _UID; 

    @OneToOne(mappedBy="city", optional=false, orphanRemoval = true, cascade=CascadeType.ALL) 
    public Mayor mayor; 
} 

@Entity 
@Table(name = "mayor") 
public class Mayor { 

@Id 
@GeneratedValue 
@Column 
public Long _UID; 

    @OneToOne(optional=false, cascade=CascadeType.ALL) 
    public City city; 
} 

如果我试试这个交易:

Mayor m = new Mayor("Ed", "Lee"); 
City c = new City("San Francisco", 100000); 
m.setCity(c); 
c.setMayor(m); 

EntityTransaction et = this.getEm().get().getTransaction(); 
et.begin(); 

this.getEm().get().persist(c); 
this.getEm().get().flush(); 

et.commit(); 

我得到以下异常:

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: test.persistence.entity.Mayor.city 

如果我检查市例如,它得到坚持之前,它在正确的地方有一个市长实例,并且这个市长实例有一个关系设置回城市实例。

optional=false只有在城市方面一切都好。

回答

1

这是因为您对两侧的cascadeAll映射有循环依赖关系。

发生什么事情是,你正在保存你的城市,保存你的市长,然后保存你的城市,这还没有被持续(因为你试图将它保存在第一位),因此冬眠不知道如何做参考DB中的城市。

您应该尝试微调市长级别的城市字段级联以删除级联类型持久性。

[编辑] 它似乎也是负责的关系是市长(因为mappedby在城市类)。我认为,当你试图坚持城市,城市应该负责关系(因此mappedBy属性应该在市长类)

+0

我是否理解正确,我应该删除'Cascade.ALL'从“公共城市城市”;在市长实体中,并将​​其注释设置为“@OneToOne(可选= false)”。我也试过这个,得到同样的例外。 – speechkey 2013-02-26 11:30:06

+0

这个关系的负责人似乎也是市长(正如城市中的地图)。我认为,当你试图坚持城市,城市应该负责关系(因此mappedBy属性应该在市长类) – benzonico 2013-02-26 11:34:47

+0

谢谢benzonico,你最后的评论做到了。如果我没有改变我的代码中的任何内容,但发送来坚持'市长'(意味着拥有一方),它就像预期的那样工作。所以我的问题是,为什么我不能坚持'城市'(意味着反面),在一对多的关系这是一个普遍的情况? – speechkey 2013-02-26 12:17:57