No owner defined between domain classes: many to many relationship - grails

These are my domain classes:
class Game {
static hasMany = [players: User]
static belongsTo = [owner: User]
}
class User {
static hasMany = [games: Game]
}
If I try to use them as they are I get No owner defined between domain classes. So I need to set the owner of the relationship. Adding static belongsTo = Game to User causes Domain classes cannot own each other in a many-to-many relationship.
The only other option I can think of is to add static belongsTo = User to the Game class but I already have a belongsTo there.
How do I model this?

class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
class User {
static hasMany = [games: Game]
}
You will have to specify one side of the relationship, as the owner, by doing this you will make User domain class as the owner of the many to many relationship.
The belongsTo field controls where the dynamic addTo*() methods can be used
from. we’re able to call User.addToGames() because Game belongsTo
User. we can’t call Game.addToPlayers().

Try this:
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}

maybe it would be better not to use "belongsTo" at all? I mean using simple field reference like
class Game {
User owner
static hasMany = [players: User]
}
FYI,
I would be careful with using "owner" field name, it might cause problems when used somehow in a closure which has its own "owner" reference (e.g. in criteria builder)
I know it caused problems back in grails 1.3.X, I don't know if it's still the case

try this:
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
class User {
static hasMany = [games: Game, owns: Game]
static mappedBy = [games:'players', owns: 'owner']
}
this settings work for me. And here is a good thread for mappedBy: GORM mappedBy and mapping difference

Related

Behaviour of belongsTo

What is the difference between
static belongsTo [author:Author]
and
static belongsTo = Author
Lets consider two domain class.
Class Author{
String name
}
Class Books{
String name
static belongsTo = Author
}
When static belongsTo = Author is kept in Books domain, it have no effects on db. However, static belongsTo = [author : Author] creates a backreference to Author class and also there is author_id column in db. So, what actually using static belongsTo = Author alone does.
This is expalined in grails docs(http://grails.github.io/grails-doc/latest/ref/Domain%20Classes/belongsTo.html).
Also, what is the difference between using following two :
Class Books{
String name
static belongsTo = [author : Author]
}
Class Books{
String name
Author author
}
static belongsTo = [author : Author] is used only for cascading purposes, Is it true or does it have different use cases.
Can anyone explain these in detail without relating it to hasOne or hasMany. Thanks in advance.
Using belongsTo without a back-reference is necessary for many-to-many associations. For example, lets assume you have the following domain classes:
class Book {
String name
Author author
static hasMany = [categories: Category]
}
class Category {
String name
static hasMany = [books: Book]
}
If you try to use them as-is you'd get an exception like this:
No owner defined between domain classes [class Book] and [class Category] in a many-to-many relationship. Example: static belongsTo = Category
The solution is to make one of the domain classes the owner of the many-to-many association. Using my example, I think it makes more sense to make the Category the owner. However, a back-reference would not work because there could be multiple Categorys. So, this is where a belongsTo without a back-reference comes in:
class Book {
String name
Author author
static hasMany = [categories: Category]
static belongsTo = Category
}
If you use static belongsTo = [author: Author] then a property named author of type Author is added to the class as a back reference. With static belongsTo = Author that does not happen.

grails: multiple belongsTo with back reference

Is it possible to have a domain class that belongs to multiple domain classes with back reference? For instance:
class Person {
List<Book> books
static hasMany = [books: Book]
}
class Organization {
List<Books> books
static hasMany = [books: Book]
}
class Book {
def owner // what's the type?
static belongsTo = [Person, Books]
}
A Book can belong to a Person or an Organization, but not both.
Person and Organization have separate sequence IDs.
The solution I came up with is:
class Book {
Long ownerID
String ownerClass
static belongsTo = [Person, Books]
static transients = ['owner']
static constraints = {
ownerId(nullable:false, blank:false)
ownerClass(nullable:false, blank:false)
}
public BookOwner getOwner() {
grailsApplication.getArtefact("Domain", ownerClass)?.getClazz()?.get(ownerId)
}
}
where BookOwner is an Interface implemented by Person and Organization. So calling a bookInstance.owner will return a Person or Organization instance, both BookOwner.
My solution works well, but it doesn't feel right - a sure sign that I am not fully understanding what I'm doing. What's the best way to implement this? Should I completely give up on having the extremely convenient back reference?
Thank you
I guess, you should have made Owner superclass. Grails will create Owner table with field class meaning child class names (in your case: Person, Organization).

belongsTo array plus hasMany ownership

I have a Grails class that both has got a many-to-many relationship (with the other side being the owner) as well as a n:1 relationship.
I could not find an answer on the web how to put the ownership into the belongsTo clause.
This is the code:
class PanelType {
static hasMany = [elements: LabValueType]
}
class LabValueType {
static belongsTo = [labUnit: LabUnit]
// This is what would be needed to have a bidirectinal n:m relationship
// belongsTo = PanelType
// static hasMany = [panelTypes: PanelType]
}
If I leave it like this, the application builds the database correctly, but I won't be able to navigate from LabValueType to PanelType.
I found one answer (from 2008!) that said I should write:
static belongsTo = [PanelType, LabUnit]
BUT this way, the field lab_unit_id is not created in the database, so it does not seem to be correct.
I have found that I can work around this problem by declaring the relationships like this:
LabUnit labUnit
static belongsTo = PanelType
static hasMany = [panelTypes: PanelType]
But somehow it is not really 100% satisfying.

No owner defined between domain classes

Currently i'm getting the following error :
No owner defined between domain classes [class mp.ra.Classgroup] and [class mp.ra.Event] in a many-to-many relationship.
The domain classes are set up as followed,
The event class:
class Event {
static hasMany = [classgroups:Classgroup]
static belongsTo = [eventgroup:Eventgroup,classgroup:Classgroup]
static constraints = {
eventgroup nullable:true
}
And the Classgroup
class Classgroup {
static hasMany = [courses:Course,events:Event]
static constraints = {
courses nullable:true
}
An Event can have multiple classgroups and a classgroup can have multiple events.
I use the belongs to property so i don't see why i'm getting this error.
EDIT: I changed The Event class and the error is gone , i dont know if this is a good solution
class Event {
Eventgroup eventgroup
static hasMany = [classgroups:Classgroup]
static belongsTo = [Eventgroup, Classgroup]
static constraints = {
eventgroup nullable:true
}
In Grails many-to-many mapping we should define an owner class between both of the associated classes.
As earlier you defined :
belongsTo = [eventgroup:Eventgroup,classgroup:Classgroup]
with this GORM tried to create a column with classgroup name under Event table, but for many-to-many association with classgroup, database should suppose to have third table to have multiple records for many-to-many associations between Event and Classgroup. So was giving such error.
Hence later when you mention :
belongsTo = [Eventgroup, Classgroup]
it worked as it just got owner information.
So here Classgroup would be the owner of association, as Event belongsTo Classgroup.
Hope this helps. Thanks.

Domain classes to track Users and Games

I'm trying to do something that seems so simple. I have a User class, and I have a Game class that matches up two Users. It's this simple:
class User {
String username
static hasMany = [games:Game]
}
class Game {
User player1
User player2
}
When I ran this, I got
Caused by GrailsDomainException: Property [games] in class [class User] is a bidirectional one-to-many with two possible properties on the inverse side. Either name one of the properties on other side of the relationship [user] or use the 'mappedBy' static to define the property that the relationship is mapped with. Example: static mappedBy = [games:'myprop']
So I did some digging and found mappedBy and changed my code to:
class User {
String username
static hasMany = [games:Game]
static mappedBy = [games:'gid']
}
class Game {
User player1
User player2
static mapping = {
id generator:'identity', name:'gid'
}
}
Now I get
Non-existent mapping property [gid] specified for property [games] in class [class User]
What am I doing wrong?
So here is probably what you want:
class User {
static mappedBy = [player1Games: 'player1', player2Games: 'player2']
static hasMany = [player1Games: Game, player2Games: Game]
static belongsTo = Game
}
class Game {
User player1
User player2
}
Edit for new rules:
class User {
static hasMany = [ games: Game ]
static belongsTo = Game
}
class Game {
static hasMany = [ players: User ]
static constraints = {
players(maxSize: 2)
}
}

Resources