Reputation: 55
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
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
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