【问题标题】:Hibernate / "absolutely necessary with bi-directional links"?休眠/“绝对需要双向链接”?
【发布时间】:2014-01-26 21:48:23
【问题描述】:

这里是官方Hibernate tutorial的摘录

首先,请记住,Hibernate 不会影响正常的 Java 语义。我们如何在 Person 和 Event 之间创建链接 单向的例子?您将 Event 的实例添加到 事件引用的集合,Person 的一个实例。如果你想 要使这个链接是双向的,你必须在另一个上做同样的事情 通过在 Event 中添加对集合的 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
} 

【问题讨论】:

    标签: java sql hibernate bidirectional-relation


    【解决方案1】:

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

    在您呈现的参与者/事件关系中,这是通过在关系的双方设置适当的实体来完成的。

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

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

    【讨论】:

    • 不错的答案。我对“chrylis”的答案发表了评论,这也可能对应于对您的答案的评论。
    【解决方案2】:

    正如其他答案所指出的,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
    

    总而言之,根据我对文档的阅读,这不是绝对必要的,但是如果未能将反向实体添加到非反向的集合中,则会导致关系不得救。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 正如您所说:“当您的代码使用 Java 代理作为数据库行时”。当两个实体分离然后在新打开的事务中使用此关系更新时建立关系的情况如何。在这种情况下,您是否同意处理第二个镜像关系不是绝对必要的?因为只要检索到两个实体中的任何一个,它就会设置其关系。我认为如果文档提到“当您处于当前事务/打开的会话中时”,文档会更加“清晰”。
      • @Mik378 “绝对必要”意味着保证正确操作。如果您不处理双方,您可能会得到但不能保证得到预期的结果,这可能会随着 JPA 提供程序甚至版本的更改而在您的脸上爆炸。这就像检查compareTo == -1;这将适用于大量Comparables,但这不是合同所说的,它不适用于许多 JRE 类。
      猜你喜欢
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多