best practice for managing collections

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

best practice for managing collections

Raj Nagappan
A couple of recent discussions reminded me that inserting / updating
cascaded objects, e.g. for collections, is a bit difficult to do and a
bit hard to get my head around. What I'm trying to understand is the
best practice for this sort of thing, or perhaps a way of using
Mybatis (or an enhancement to it) that I haven't thought of. A simple
example from a previous topic to illustrate what I mean:

An Author has a collection of Blogs. Each Blog has only one Author but
an Author has many Blogs.

public class Author {
  private long id;
  private String name;
  private List<Blog> blogs;
}

public class Blog {
  private long id;
  private long authorId;
  private String subject;
  private String content;
}

So we have a method on Author to add a new Blog:

public void addBlog(Blog blog)
{
  blogs.add(blog);
  blog.setAuthorId(this.getId());
  // need to persist change on blog now
}

Persisting the change in the blog state is the problem that I am
scratching my head over. One solution is to call a DAO or mapper in
the addBlog() method above to update the blog object, but this breaks
the abstraction between model and persistence, because we have these
DAO calls scattered throughout the Author class.

Another solution is to implement a cascade at the DAO level, so we
would have an AuthorDAO.update() method that would look something
like:

public void update(Author author)
{
  //sql mapper update for author
  for (Blog blog : author.getBlogs())
  {
    getBlogDao().update(blog);
  }
}

This second solution has a few issues as well. First, it's calling a
lot of unnecessary updates on the blog objects, which multiply if
those blogs themselves have collections. Second, we made the change to
the blog object, but we are calling update on the parent author even
though it didn't actually change.

The third solution that I can think of is to simply call update on the
blog object by the client code, eg:

author.addBlog(myBlog);
blogDao.update(myBlog);

Which seems straightforward, but doesn't work well with side-effects
to the rest of the collection. E.g. if I have a PhotoSet which
contains Photos and I move a photo up in the order we have:

public class Photo
{
  private int id;
  private int photoSetId;
  private int sortOrder;
}

public class PhotoSet
{
 private int id;
 private List<Photo> photos;

  public void movePhotoUp(Photo photo)
  {
    swapOrder(photo, getPredecessor(photo));
    // swapOrder changes the sortOrder field on each photo, ie. swaps
their values
    // so that a re-sort makes their order swap
  }
}
so any client code which went:

photoSet.movePhotoUp(myPhoto);
photoDao.update(myPhoto);

would correctly update myPhoto's sortOrder field but not myPhoto's
predecessor.

So after that long-winded discussion what I'm asking is what is the
best way to manage a collection within it's parent container?

Raj.