开发者

How to prevent a loop in a bi-directional relationship

开发者 https://www.devze.com 2023-03-05 06:30 出处:网络
Say we have the following two entities. Library public class Library { private Collection<Book> books = new ArrayList<Book>();

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 libra开发者_高级运维ry)
    {
        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.


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.


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 corresponding has methods (hasBook in Library and hasLibrary in Book). Before calling the add or remove 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?

public boolean add(Book book)
{
   book.setLibrary(this);
   return books.add(book);
}
public boolean remove(Book book)
{
   book.setLibrary(null);
   return books.remove(book);
}


In your proposed solution, couldn't you check references for equality to avoid loop?

public boolean add(Book book)
{
   if(book.getLibrary != this) book.setLibrary(this);
   return books.add(book);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消