trnsnt
trnsnt

Reputation: 694

How to represent a 1..n relationship in Java

Let's say I have two classes: one for Band and one for CD. I want to be able to access easily all CD from one Band and to find the Band of a CD.

My solution is to have a field Band in CD, and a ArrayList<CD> in Band.

But I don't find this is a good solution. Does anyone know of a better design for this scenario?

Upvotes: 6

Views: 2203

Answers (4)

Jonas Eicher
Jonas Eicher

Reputation: 1511

I see why you dislike the solution.

You are only storing the information once, but you have to update changes in both classes.

If you change the Band of a CD, you have to remove the CD from the old Band, set the Band in the CD, then add it to the new Band.

That is of course complicated and prone to error.

Your classes don't have simple getters/setters. Instead, you have to implement a lot of logic in your domain classes to keep consistency.

The advantage is, of course, that you always have a the Band of a CD accessible and vice versa. Its a trade-off. A neccesary one, should you, for example, use a CD's Band as part of its equals implementation.

Here is an interesting alternative, that may be advantegous in some situations:

Use your classes Band and CD only as simple POJOs and use another class (i.e. MusicService) to resolve the relation:

class MusicService {
  Band getBand(CD cd);
  List<CD> getCDs(Band band);
  addCD(Band band, CD cd);
}
  • Advantages: Separation of concerns, stateless services
  • Disadvantage: More code

Upvotes: 4

Paolo Brandoli
Paolo Brandoli

Reputation: 4750

You are not storing the information twice: CD just holds a pointer to the class Band. If would have done in C++ then this would have required some thinking (e.g. a weak_ptr to Band in CD to avoid circular references), but in Java the GC will take care of removing both objects when Band is not referenced anywhere else.

You can ensure some consistency (like a CD is only in one band) by writing some code that takes care of this, like the code below (WARNING: NOT TESTED):

class Band
{
 private List<CD> m_cds;

 public void addCD(CD cd)
 {
  id(cd.getBand() == this)
  {
   return;
  }
  if(cd.getBand() != null)
  {
   cd.getBand().removeCd(CD cd);
  }
  cd.setBand(this);
  m_cds.add(cd);
 }

 public void removeCd(CD cd)
 {
  cd.setBand(null);
  m_cds.remove(cd);
 }
}


class CD
{
 private Band m_band;

 public void setBand(Band band)
 {
  m_band = band;
 }

 public Band getBand()
 {
  return m_band;
 }
}

Upvotes: 0

dic19
dic19

Reputation: 17971

Your solution totally makes sense. Actually that's the principle JPA works with. See Java Persistence/OneToMany. JPA is a pretty good reference on how implement your own ORM.

Upvotes: 1

Christina
Christina

Reputation: 1

You could have a Set of CDs in the Band class.

Alternatively, keep a unique ID in the Band class which will map each unique Band with multiple CDs.

There is no need to have a Band field in CD, as per my understanding.

Upvotes: 0

Related Questions