Rene
Rene

Reputation: 55

Domain using addTo an Map causing error

I've a Team with exactly 4 Players. The position of each of the player is important, so I thought I'm on a good way using a Map for my players, with the keys: pos1, pos2, pos3, pos4

class Team {

Map players = [pos1:null, pos2:null, pos3:null, pos4:null]
static hasMany = [players:Player]

League league

static belongsTo = [club:Club]

static constraints = {
    league nullable:true
    players nullable:true

}
}

and my Player:

class Player{

static belongsTo = [club:Club, team:Team]

String firstname
String lastname

Team team



static constraints = {
    team nullable:true
    firstname nullable:true
    lastname nullable:true

}

public String fullname() {
    return firstname + " " + lastname + " - " + team?.id ?: "R"
}
}

I use the addToPlayers() method to get the Player automated updated but I get an error when I try the following:

def player = new Player(firstname:"Peter", lastname:"Pan")
def team = new Team()
team.addToPlayers([pos1:player])

The Stacktrace is saying:

Groovy.lang.MissingMethodException: No signature of method:
org.hibernate.collection.PersistentMap.add() is applicable for argument types:
(at.panda.Player) values: [at.panda.Player : null]
Possible solutions: any(), any(groovy.lang.Closure), any(groovy.lang.Closure), wait(),
wait(long), get(java.lang.Object)

at at.panda.PlayerController$_closure4.doCall(PlayerController.groovy:39)

at at.panda.PlayerController$_closure4.doCall(PlayerController.groovy)

at java.lang.Thread.run(Thread.java:662)

That cost me a lot of time and i hope someone can help me. I do not need to stick to the "Map" if you have a better solution.

Upvotes: 1

Views: 847

Answers (2)

Dónal
Dónal

Reputation: 187499

Personally, I would model your domain like this:

class Team {

  //Map players = [pos1:null, pos2:null, pos3:null, pos4:null]
  static hasMany = [players:Player]

  // The reference to league is now specified below in belongsTo       
  //League league

  static belongsTo = [club:Club,league:League]

  static constraints = {
    league nullable:true

    // must have 4 players
    players(size: 4..4)
  }
}

class Player{

  // Remove the reference to club as this can be retrieved through the Team
  static belongsTo = [/*club:Club,*/ team:Team]

  String firstname
  String lastname
  Integer position

  // Remove this duplicate reference to team
  //Team team        

  static constraints = {
    team nullable:true
    firstname nullable:true
    lastname nullable:true 

    // This should ensure that you can't create 2 players with the same position
    // in the same team
    position(unique:'team')   
  }
}

This model will make it easier to get all the players ordered by position and if you decide that you want to change the number of players, all you need to do is change the constraint players(size: 4..4)

I'd consider adding a addPlayer(Player player) method to Team that takes care of setting the position property correctly.

If haven't tested any of the code above, so handle with care.

Upvotes: 0

ataylor
ataylor

Reputation: 66059

If you have a Map property in a domain object, the key and value must both be Strings: Grails Manual: Object Relational Mapping.

But why are you using a map for your players? If you have exactly four players, just define your Team as:

class Team {
    Player pos1
    Player pos2
    Player pos3
    Player pos4
    ...
}

Upvotes: 2

Related Questions