Q:

Hibernate Best Practices: Avoiding Many-To-Many and 'exotic' relationships

The hibernate best practices states that many-to-many associations are rare and should be avoided.

Do not use exotic association mappings:
Practical test cases for real many-to-many associations are rare. Most
  of the time you need additional information stored in the "link
  table". In this case, it is much better to use two one-to-many
  associations to an intermediate link class. In fact, most associations
  are one-to-many and many-to-one. For this reason, you should proceed
  cautiously when using any other association style.

A basic and common case would be: user can be in more than one team and a team can have more than one member.
Is there an alternative to using @ManyToMany, other than creating an entity for the join table? In the case of team/member, there is no additional data in the join table, so having Team>TeamMembership>User is not so practical.

A:

There is nothing intrinsically wrong with using @ManyToMany but in practice, you rarely have the opportunity to use it.  Usually you need additional attributes on the link itself, at which point, the relationship becomes an entity of its own.
One example from my experience was the kind of person/team relationship you described.  I used a @ManyToMany at first, but had to turn it into a @OneToMany once I needed to add an effective-date on the relationship  (person belongs to team at specific point in time).

A:

One of the problems with @ManyToMany is that models change. If you need to add a field to the association, then you have a few choices. You can either refactor the model so that the association becomes an entity (read link class). Or you can make the association even more exotic, for example @MapKeyJoinColumn. In either case, the future refactoring effort could be saved by designing the model right in the first place.
Furthermore, using one of these exotic many-to-many mappings tends to bring the model closer to edge cases where test coverage is lower and real world usage is lower. This in turn increases the risk of encountering unsupported or undersupported features as well as unresolved and undiscovered bugs.
Finally just because hibernate gives you a way to do it, doesn't mean you should use it. I've seen too many cases in my experience of developers using a certain feature in hibernate a way it was not intended which led to other design implications, and limitations that caused more trouble and headaches than they were worth.

