How to specify Association in Grails - grails

I have got a domain class Track
class Track{
static belongsTo = [createdBy: User, modifiedBy: User, Course]
}
But its giving me error, Finally i dont want to have course object[course: Course] but only have to specify that it belongs to Course [Course]. How to do this

I think you are using the GORM associations a bit too extensively. belongsTo indicates ownership, and the GORM associations, in general, indicate more about the cascading relationship between objects than anything else.
If you only want to associate User with your Track, you just need to have the createdBy and modifiedBy fields, which don't need to be in any special sort of association. Then you would have static belongsTo = [Course] to show that the Course owns the Track, meaning that if you deleted the Course, that the Track would get deleted as well.
Here's the class I think you are looking for:
class Track {
User createdBy
User modifiedBy
static belongsTo = [Course]
}

Related

GORM domain variable without belongsto

What is the different in GORM between
class Books {
Author author
}
and
class Books {
static belongsTo = [author: Author]
}
Does cascading rules changes in these two approaches? Also, when to use belongsTo and more importantly, when not to use belongsTo in Grails ?
Yes, belongsTo is intended for controlling cascades of saves and deletes. You may reference the full documentation here http://docs.grails.org/latest/ref/Domain%20Classes/belongsTo.html but to summarize (and in case the URL dies someday):
Use belongsTo to indicate ownership. Saves or deletes to the parent will cascade to the child. In your example, if the Author is deleted, his Books will be too (assuming Author hasMany Books
Do not use belongsTo if you just want to indicate a relationship with no ownership on either side and no automatic cascading of saves or deletes.

Domain modeling using GORM in grails, how to represent an association

I am learning grails and I came up with a use case. In my use case, a product has many users and each user can have many roles.
Here is my product class:
class Product {
String name
String description
String vision
Date startDate
Date endDate
static hasMany = [users : User, contributors : User, watchers : User, approvers : User]
static belongsTo = User
static constraints = {
}
}
Here is my User class:
class User {
static constraints = {
}
String fullName
String email
static hasMany = [roles : Roles, products : Product]
}
Here is the Roles Enum:
public enum Roles {
PRODUCTOWNER ('ProductOwner'),
APPROVER ('Approver'),
CONTRIBUTOR ('Contributor'),
WATCHER ('Watcher')
}
My question is specifically about the association between Product and User. I want to represent the fact that a product can have many users in different roles. Also, each user can be part of multiple products with a different role in each product. Is this the right way to represent this relationship? Also, I should be able to remove and add users to products and vice versa. What this also means is that, users can keep moving between roles and can move in and out of products. In this scenario, I probably don't want cascades to happen. How do I prevent automatic cascades from happening to CRUD operations for this relationship?
Thanks.
I think rather than having roles and products in User.groovy, it will be better if you create a separate domain like UserProductRole. As you said user will have different role in different products then creating a separate domain makes more sense in business usecase and also doing queries
class UserProductRole{
Role role
static belongsTo = [user:User,product:Product]
static constraints = {
user (unique:['product','role']
}
}
You can create composite key but I generally dont perfer it because it makes querying bit difficult.
And now you need to change hasMany in User and Product like following
[userProducts:UserProductRole] rather then having users or products

Removing association from M:N relationship when deleting an entity

In my domain I have a many-to-many relationship. The problem is that GORM forces me to define owner entity but I don't think that either side "owns" the relation.
class User {
String username
String password
static hasMany = [organizations: Organization]
static belongsTo = Organization
static constraints = {
}
}
class Organization {
String name;
static hasMany = [members: User]
}
In this case I'm obviously not allowed to delete User who is in some organization (because Organization "owns" the relation). I would like to be able to delete both entities and on delete simply remove the relation (row from user_organization table). Is it possible or do I have to write this logic myself (if so, what would be the best way to implement this)?
You are allowed to delete both sides of the relationship, no matter who is the "owner". The belongsTo just applies the proper cascading so you don't have to.
In your example if you want to delete a user you first have to remove the relationship. So, in order to delete a user you do:
organization.removeFromMembers(user)
user.delete()
And if you delete an organization, since it is the "owner", you just don't need to use removeFrom*.

Deleting m-to-m is also trying to cascade delete a one-2-one

I have the following Domains
class Committee {
String name
BoardCommitteeType boardCommitteeType
Date dateCreated
Date lastUpdated
User createdBy
User modifiedBy
static belongsTo = [
board: Board,
]
static hasMany = [
members: User
]
}
class User {
static hasMany = [
committees: Committee,
]
static belongsTo = [
Board, Committee
]
}
The problem is that when I attempt to do a board.removeFromCommittees(committee) I'm getting the following exception:
deleted object would be re-saved by cascade (remove deleted object from associations): [com.wbr.highbar.User#1];
I understand what that means. What I don't understand is why I am getting it. The other interesting bit is that if I make creatdBy and modifiedBy in the Committee instance null, the delete works just fine. That's why I am thinking that GORM is trying cascade the one-2-one. My theory is that is has something to do with the fact User belongsTo a Committee. But I don't know how to fix the problem.
The cascading delete is effected by the belongsTo relationships between your domain classes.
Since Committee belongsTo Board, when a Board gets deleted, the delete cascades to the Committee. Since User belongsTo Committee, when a Committee gets deleted, the delete cascades to the User.
The solution to your problem is to remove the User belongsTo Committee relationship.
Notes on your domain model as a whole:
You have a lot of many-to-many relationships. They're not necessarily wrong, but they might be overcomplicating things. You could probably get away with just using:
class Committee {
static hasMany = [boards: Board, users: User]
}
class Board {
static hasMany = [users: User]
static belongsTo = Committee // this is the only belongsTo you need, since if a
// committee is dissolved, presumably the board
// will be dissolved as well (unless you have
// cross-committee boards)
}
class User {
// doesn't define any relationships,
// let the Committee/Board domains handle everything
// also, this is presuming that users are at a higher level than committees, i.e.
// a user could belong to multiple committees
}

Grails/GORM: The meaning of belongsTo in 1:N relationships

In an ordinary one-to-many mapping the "one"-side is the owner of the association. Why would anyone use the belongsTo-mapping for such a mapping? Am I missing some side-effect of specifying belongsTo?
In other words: what are the effects of specifying a belongsTo-mapping in GORM vs. not specifying it?
Whether to specify belongsTo depends upon the type of referential action you want.
If you want Grails to do On Delete, CASCADE referential action, then DO specify belongsTo. If you want Grails to do On Delete, RESTRICT referential action, then DON'T specify belongsTo.
e.g.
// "belongsTo" makes sense for me here.
class Country {
String name
static hasMany = [states:State]
}
class State {
String name;
// I want all states to be deleted when a country is deleted.
static belongsTo = Country
}
// Another example, belongsTo doesn't make sense here
class Team {
String name
static hasMany = [players:Player]
}
class Player {
String name
// I want that a team should not be allowed to be deleted if it has any players, so no "belongsTo" here.
}
Hope this helps.
Specifying belongsTo allows Grails to transparently cascade updates, saves and deletes to the object's children. Without belongsTo, if you attempt to delete a master record, you'll end up getting a foreign key violation if it has any details it owns.

Resources