Friday, February 12, 2010

Grails Many to Many with Lists Problem

The Problem

Having problems persisting your many to many relationships using Lists? Well you've come to the right place!

The Classes

We have a many to many relationship between a Player and a Squad, as a squad can have many players, and a player can belong to many squads.

We also want to know if the player is active in the squad, so we have another class modelling the relationship, Membership with an active property.

Let's have a quick look at our Domain classes...
We can persist he classes like this...


By default hasMany creates a java.util.Set of Memberships. That's fine, but Sets are unordered, and because I'm a bit fussy, I really want my memberships orders. There are a few ways to achieve ordering (I'm not going to cover them all here). The way I want to do it is by explicitly defining memberships as a List.

The Error

All fine and dandy. Well, actually, no. If we try and persist our domain classes now, we are met with an unexpected (and somewhat incomprehensible) error...

org.hibernate.MappingException: Duplicate property mapping of 
_membershipsIndexBackref found in smitek.fiveasider.Membership

All we did was change our collection from a Set to a List. For me this is a bit harsh, and hopefully something that can be handled in Grails going forward. As you can tell from the error message, this error is occurring down in Hibernate.

After lots of messing around trying various things I finally worked out a way to get this working, with a hint from this link.

The Solution!

By giving the collection of memberships a unique name in the Player and Squad classes we get round the problem.

6 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. nice,
    You could also try using an index column
    http://www.grails.org/doc/latest/ref/Database%20Mapping/indexColumn.html

    ReplyDelete
  3. Very nice..Thanks a lot for the post..works well for me..

    ReplyDelete
  4. I'm hitting this same bug using Grails 2.0.4. Unfortunately, we are pretty far into the development of our app. I don't think renaming all the collections is an option.

    We uncovered this issue when we discovered we needed the back reference for some objects that didn't have it. Added the belongsTo and *KABOOM* app won't start.

    I'm scrambling for a solution now.

    ReplyDelete
  5. Great! It saved my time.

    ReplyDelete
  6. Thank you for a great tutorial! I get (unsave) message after adding elements to map. I am trying to find its answer over stackoverflow:-
    http://stackoverflow.com/questions/21518706/unsaved-data-in-groovy-in-many-many-relationship?noredirect=1#comment32489850_21518706

    ReplyDelete

About...

This is the about stuff