如何防止双向关系中出现环路
假设我们有以下两个实体。
图书馆
public class Library
{
private Collection<Book> books = new ArrayList<Book>();
public boolean add(Book book)
{
return books.add(book);
}
public boolean remove(Book book)
{
return books.remove(book);
}
}
图书
public class Book
{
private Library library;
public setLibrary(Library library)
{
this.library = library;
}
}
这是一种双向关系,很可能很快就会破裂。即使您将一本书添加到图书馆,该书的图书馆也不会更新。即使您更新了一本书的图书馆,图书馆也不会更新。
那么,如何才能很好地维持这种双向关系呢?我当然可以在 setLibrary
中执行 add
+remove
,反之亦然,但据我所知,这会导致循环这可能会以 StackOverflowError 结束。
Say we have the following two entities.
Library
public class Library
{
private Collection<Book> books = new ArrayList<Book>();
public boolean add(Book book)
{
return books.add(book);
}
public boolean remove(Book book)
{
return books.remove(book);
}
}
Book
public class Book
{
private Library library;
public setLibrary(Library library)
{
this.library = library;
}
}
This is a bi-directional relationship which will most likely break pretty quick. Even though you add a book to a library, the library of the book is not updated. And even though you update the library of a book, the library isn't updated.
So, how would you maintain this bi-directional relationship in a good way? I could of course just do an add
+remove
in the setLibrary
and vice versa, but this would as far as I can see cause a loop which would probably end in a StackOverflowError
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
定义关系的“所有者”。图书馆“拥有”这本书还是这本书拥有图书馆?
该问题的答案告诉您谁更新了“从属”实体。
我觉得图书馆拥有这本书,所以“将书添加到图书馆”代码应该进入图书馆,然后更新后面的引用。
Define a "owner" for the relation. Does the library "own" the book or does the book own the library?
The answer to that question tells you who updates the "slave" entity.
I feel that the library owns the book, so the "add book to library" code should go into the library which will then update the back references.
虽然我推荐 Aaron 定义关系所有者的方法,但允许
set
/add
/remove
方法保留在原来位置的替代方法是还定义相应的has
方法(Library
中的hasBook
和Book
中的hasLibrary
) 。在关系另一端调用add
或remove
方法之前,首先查询它是否已存在,如果存在则不调用它。While I would recommend Aaron's method of defining a relationship owner, an alternative that allows the
set
/add
/remove
methods to remain where they are is to also define correspondinghas
methods (hasBook
inLibrary
andhasLibrary
inBook
). Before calling theadd
orremove
method on the other end of the relation, you first query if it already exists, and if it does don't call it.我是不是傻了?
Am I being dumb?
在您提出的解决方案中,您不能检查引用是否相等以避免循环吗?
In your proposed solution, couldn't you check references for equality to avoid loop?