Hibernate /“双向链接绝对必要”?

时间:2014-01-26 21:48:24

标签: java sql hibernate bidirectional-relation

以下是官方Hibernate tutorial

的摘录
  

首先,请记住Hibernate不会影响普通的Java   语义。我们是如何在一个人和一个事件之间创建一个链接的   单向的例子?您将事件的实例添加到   Person实例的事件引用的集合。如果你想   要使这个链接双向,你必须在另一个上做同样的事情   通过在事件中添加对集合的Person引用。 :此   “设置双方链接”的过程是绝对必要的   使用双向链接。

     

许多开发人员采取防御性计划并创建链接管理方法   正确设置双方(例如,在Person中):

protected Set getEvents() {
    return events;
}

protected void setEvents(Set events) {
    this.events = events;
}

public void addToEvent(Event event) {
    this.getEvents().add(event);
    event.getParticipants().add(this);
}

public void removeFromEvent(Event event) {
    this.getEvents().remove(event);
    event.getParticipants().remove(this);
}

在这种情况下,“绝对”一词是什么意思? :

  • 这意味着建议只要当前逻辑过程结束就保持关系一致,但显然会出现持久性?
  • 这意味着如果不设置另一方(不拥有关系),持久性可以严格吗?

换句话说,如果我的“添加”方法是:

会发生什么
public void addToEvent(Event event) {
    this.getEvents().add(event);
    //event.getParticipants().add(this); without this line
} 

3 个答案:

答案 0 :(得分:3)

bi-directional关系允许参与该关系的两个实体获得该关系另一侧的实体。当您插入参与双向关系的这些实体时,您负责管理关系的两个方面。

在参与者/事件关系中,您通过在关系的两侧设置适当的实体来完成此操作。

因此,如果您尝试为参与者添加事件,则必须将事件添加到参与者Collection<Event>,并且必须将参与者添加到事件的Collection<Participant>。您不能简单地将该事件添加到参与者的Collection<Event>,并希望hibernate在事件的Participant中填充Collection<Participant>

如果您未能将Participant添加到Collection<Participant>以查找事件,Collection<Participant>将与数据库不同步,并且可能无法插入,具体取决于已建立的约束和级联设置。

答案 1 :(得分:1)

正如其他答案所指出的那样,hibernate不会破坏正常的Java语义。将参与者添加到事件的集合中不会将事件透明地添加到参与者的集合中。 负责设置它。

According to the docs(不是教程):

  

仅对关联的反向结束所做的更改不会保留。   ...   非反面用于将内存中表示保存到数据库中。

在这里,直接来自文档Item的代码示例是关联的反面:

category.getItems().add(item);          // The category now "knows" about the relationship
item.getCategories().add(category);     // The item now "knows" about the relationship

session.persist(item);                   // The relationship won't be saved!
session.persist(category);               // The relationship will be saved

总之,从我对文档的阅读来看,它不是绝对必要的,但是如果没有将反面实体添加到非反面的集合中将导致关系不得救。

答案 2 :(得分:0)

这意味着当您添加关系的一侧时,两个数据结构的内存中副本不会自动更新,因此当您的代码使用数据库行的Java代理时,您可能会添加一个事件参与者的事件列表,但事件不会显示参与者,并且(合理地)依赖于两者同步的任何代码都将失败。这是JPA中一个令人讨厌的陷阱,但它不是特定于Hibernate的,并且似乎不会很快消失。