Java 如何防止双向关系中的循环
假设我们有以下两个实体 库Java 如何防止双向关系中的循环,java,entity-relationship,foreign-key-relationship,entities,bidirectional,Java,Entity Relationship,Foreign Key Relationship,Entities,Bidirectional,假设我们有以下两个实体 库 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 book
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);
}
}
这是一种双向关系,很可能很快就会破裂。即使向库中添加了一本书,该书的库也不会更新。即使你更新了一本书的图书馆,图书馆也不会更新
那么,您将如何以良好的方式保持这种双向关系?当然,我可以在setLibrary
中执行add
+remove
,反之亦然,但据我所知,这将导致一个循环,该循环可能以StackOverflowError
为关系定义一个“所有者”而结束。图书馆是“拥有”这本书还是这本书拥有图书馆
这个问题的答案告诉您谁更新了“从属”实体
我觉得图书馆拥有这本书,所以“将书添加到图书馆”代码应该进入图书馆,然后更新后面的参考资料。我是不是傻了
public boolean add(Book book)
{
book.setLibrary(this);
return books.add(book);
}
public boolean remove(Book book)
{
book.setLibrary(null);
return books.remove(book);
}
在您提出的解决方案中,您不能检查引用是否相等以避免循环吗
public boolean add(Book book)
{
if(book.getLibrary != this) book.setLibrary(this);
return books.add(book);
}
虽然我推荐Aaron定义关系所有者的方法,但另一种方法允许
集合
/添加
/删除
方法保持不变,即也定义相应的has
方法(库中的hasBook
和库中的hasBook
)。在调用关系另一端的add
或remove
方法之前,首先查询它是否已经存在,如果不存在,则不调用它。no。问题是,如果您除此之外还执行this.books.remove(此);这本书=书;this.books.add(this)在setLibrary
类中的code>。好的,那么这就是通常的做法?因此在这种情况下,Book
可能是哑的,您只需在Library
类中调用setLibrary
。@Svish:是的,这就是想法,您只能将书籍添加到库中,然后设置书籍的库。不能直接在书本上设置库。是。这是一个解决办法,因为Veredesmarld的建议在今天的计算机上太慢了。如果问题“这本书已经在图书馆里了吗”的复杂性是O(1)(无论图书馆有多大,都需要相同的时间),那么我们可以负担两边的附加代码。这是有意义的。那么我想我会这样做:)那不行:如果这本书已经在另一个图书馆,书中的图书馆参考不会被更新,你最终会得到一本在几个图书馆(从图书馆的角度来看)的书,但这本书会认为它只是在其中一个图书馆。如果检查速度快,这将是一个完美的解决方案。今天的计算机仍然太慢了:(@Aaron Digulla:我同意,这就是为什么我在前面说我更喜欢你的方法,但我仍然觉得值得指出这是一个选择。是的,我会按照@Aaron的建议去做,但这也是一个很好的观点,我可能会在其他情况下使用:)
public boolean add(Book book)
{
if(book.getLibrary != this) book.setLibrary(this);
return books.add(book);
}