1

I have class "Book" and class "Author" in Java.There is many-to-many relationship between Book and Author.

Book Class :

public class Book
{
    int ISPN;
    String title;
    String description;
    int pageCount;
    public ArrayList<Author> Authors;
}

Author Class :

public class Author 
{
    int authorID;
    String firstName;
    String lastName;
    ArrayList<Book> books;
}

I want to serialize an object of Book or Author, but there will be an infinite recursion, as every Book has a list of his associated authors, who have their associated books, etc to infinity. So how to handle situations like this ?

Sorry for my bad English.

Amal
  • 25
  • 7

1 Answers1

0

As far as you have many-to-many relationship you need to have some storage in order to store all data (something like database). And the best approach IMHO is make you lists transient and restore items from this storage when you are restoring your serialisable. If it is really database in your case you can use some in-memory cache in order to make it faster.

[EDIT]:

Here is alternative implementation with storage:

Storage.java:

public class Storage implements Serializable {
    private final HashMap<Integer, Book> books;
    private final HashMap<Integer, Author> authors;

    public Storage() {
        books = new HashMap<>();
        authors = new HashMap<>();
    }

    public void addBook(Book book) {
        books.put(book.ISPN, book);
    }

    public void removeBook(Book book) {
        books.remove(book.ISPN);
    }

    public void addAuthor(Author author) {
        authors.put(author.authorID, author);
    }

    public void removeAuthor(Author author) {
        authors.remove(author.authorID);
    }

    public Author getAuthor(Integer authorId) {
        return authors.get(authorId);
    }

    public Book getBook(Integer bookId) {
        return books.get(bookId);
    }
}

Book.java:

public class Book implements Serializable {
    int ISPN;
    String title;
    String description;
    int pageCount;
    ArrayList<Integer> AuthorIds;
    Storage storage;

    public Book(Storage storage) {
        this.storage = storage;
    }

    public void addAuthor(Author author) {
        storage.addAuthor(author);
        AuthorIds.add(author.authorID);
    }

    public List<Author> createAuthorsList() {
        List<Author> authorList = new ArrayList<>();
        for (Integer authorId : AuthorIds) {
            authorList.add(storage.getAuthor(authorId));
        }
        return authorList;
    }
}

Author.java:

public class Author {
    int authorID;
    String firstName;
    String lastName;
    ArrayList<Integer> bookIds;
    Storage storage;

    public Author(Storage storage) {
        this.storage = storage;
    }

    public void addBook(Book book) {
        storage.addBook(book);
        bookIds.add(book.ISPN);
    }

    public List<Book> createBooksList() {
        List<Book> bookList = new ArrayList<>();
        for (Integer bookId : bookIds) {
            bookList.add(storage.getBook(bookId));
        }
        return bookList;
    }
}

The only one (but big) disadvantage of using this implementation, that after deserialisation you will have multiple instances of Storage class with same data. It order to optimize this I would suggest you to make storage entries as transient members and serialize them separately.

Community
  • 1
  • 1
Oleksandr
  • 6,226
  • 1
  • 46
  • 54
  • Thanks alot for your answer. But I don't have any type of storage except the file that I want to serialize these objects in it, and I'm forced to have the list in Book class as a list of Author objects, and the list in Author class as a list of Book objects. I think that maybe I can make one of these lists transient as you pointed above, and restore items of the transient list from the serializable list when I am restoring my serialisable. – Amal Dec 17 '15 at 10:40
  • @Amal, I think making only one of lists is transient is a not good solution. Check my edit, I added alternative implementation. – Oleksandr Dec 17 '15 at 11:49
  • The implementation is clear :) . But why making only one of lists transient is not a good solution ? – Amal Dec 17 '15 at 12:26
  • @Amal, how are you going to restore this array? You need to implement some extra logic and iterate over all books in all Authors (or vice versa). And this mean than you need to store links to all Auctions, otherwise you can loose some dependencies. – Oleksandr Dec 17 '15 at 12:34
  • Actually I have BooksDistributor class which has a list of Books and a list of Authors, and I want to serialize the object of this class -sorry I did not mention this- . So I'm thinking about making the Authors' list in Book transient and after deserialize the BooksDistributor, I will iterate over all books in all Authors and add each author to the authors' list of his books. – Amal Dec 17 '15 at 13:07
  • @Amal, it sounds good. In my second implementation Storage entry is similar to your BooksDistributor. Hope, I've helped you :) – Oleksandr Dec 17 '15 at 13:19