I'm attempting to model an organizational tree in grails. What I have works, but I have a couple of questions about it.
Here's my 'Organization' class:
class Organization {
String title
Organization parentOrg
static hasMany = [ childOrg: Organization ]
static mappedBy = [
childOrg: 'parentOrg',
parentOrg: 'childOrg'
]
static constraints = {
parentOrg nullable: true
}
}
Now, when I create a new 'Organization' like this:
def newOrg = new Organization(
title: 'New Organization',
parentOrg: oldOrg).save()
Everything works well, and the relationship to the parent seems modeled correctly.
But if I try to call something like oldOrg.childOrg.each I will get no results unless I have also called oldOrg.addToChildOrg(newOrg).
Furthermore, when I check the tables that are generated, the only reference to this relation is the parent_org_id column on the Organization table.
Now, I realize that this is all that is necessary to also determine the childOrg relations, but I don't notice ANY change in the database from before I call oldOrg.addToChildOrg(newOrg) to after!
So where is this relation getting stored when I call addToChildOrg when I don't see anything change in the database?
Also, how can I have this relation setup to automatically create the childOrg relation when I add the parentOrg? I don't think I should have to call addToChildOrg when I'm adding the parentOrg. It should be implied.
Thanks!
Use a hasOne association to store the foreign key reference in a bidirectional one-to-one.
Since you don't want to add the relationship from other side each time so you can make a setter to ease your work, like-
setParentOrg(parentInstance){
this.parentOrg = parentInstance
parentInstance.childOrg = this
}
Now when you do organisationInstance.parentOrg = parentInstance, the setter gets invoked for you, and the relationship is setup the way you want.
if I'm correct you're missing belongsTo definition, because you need to define that every instance of Organization is owned by its parentOrg instance.
try this class declaration:
class Organization {
String title
Organization parentOrg
static belongsTo = [parentOrg: Organization]
static hasMany = [ childOrg: Organization ]
static mappedBy = [ childOrg: 'parentOrg']
static constraints = {
parentOrg nullable: true
}
}
Related
While migrating an existing app from Grails 2.5 to 3.1, I ran into an odd issue with a bi-directional one-to-one relationship.
Imagine a simple model with a User and Employee objects. A User represents a generic user account. Not all users are Employees but all Employees are Users. Moreover Employees have references to managers, supervisors, etc (also User instances). User is the owning side of the relationship.
class User {
Employee employee
static mappedBy = [employee: "user"]
static hasOne = [employee: Employee]
static constraints = {
employee(nullable:true)
}
}
class Employee {
User user // represents employee's own account, a bi-directional one-to-one
User supervisor // represents a supervisor
static belongsTo = [user: User]
static constraints = {
user(unique:true)
supervisor(nullable:true)
}
}
The trouble after upgrading to Grails 3 is that in the create mode, this results in supervisor_id column of employee table being generated as NOT NULL, whereas in Grails 2 it was nullable as expected (with only user_id being NOT NULL).
I tested this with Grails 3.1.12 and 3.2.0, getting the same behavior with both. Am I doing anything stupid in my domain class declarations? I've tried multiple mappings to achieve the same behavior as in Grails 2.5 without luck. In some cases I'm even getting a foreign key on both sides of the relationship...
I don't know why your code was working with previous version of Grails, but it is wrong.
When you use hasMany and belongsTo, it is not necessary to define other property in the child object, and you don't need also to use the mappedBy property on the parent, and the same with the parent (property employee at User)
Grails doesn't need anything else to know which is the bidirectional property on both classes, and the constraint user(unique : true) neither.
So your classes should look like this:
class User {
static hasOne = [employee: Employee]
static constraints = {
employee(nullable: true)
}
}
class Employee {
User supervisor // represents a supervisor
static belongsTo = [user: User]
static constraints = {
supervisor(nullable:true)
}
}
It could be nice to know how is your DB structure. But in this way all foreign keys are stored in the employee table. But of course you could navigate from both entities. If you have different structure you could map your current database with this model. See this
employee.user
user.employee
I want to create a domain class as like , One user can post many orders [Bidirectional] and one order can be liked by many users [unidirectional].
I have written a domain class as shown below ,
Class User {
String userName;
List orders
static hasMany = [Order]
}
Class Order {
String orderId
String orderName
//Indicates this order belongs to only one user
static belongsTo =[owner : User ] // Bidirectional
//Indicates order can be liked by many users
static hasMany = [likedUser : User] //Unidirectional
}
But I am getting am error saying invalid schema . Any body please help...
This post looks similar to my question but I am not getting , Please help.
First, order is a reserved word in SQL. Since GORM by default creates a table with the same name as your class, you'll need to either rename your class or provide a different name to use when mapping to SQL tables.
For example:
class Order {
static mapping = {
table 'user_order'
}
// ...
}
Another problem is that Order contains two associations to User. You need to tell GORM which one of these that is the bi-directional association from User to Order. That can be achieved using mappedBy, like this:
class User {
String userName
static hasMany = [orders: Order]
static mappedBy = [orders: 'owner']
}
Hope this helps.
I'm new to Grails, some things are still vague for me.
I want to create a Twitter-like app. As a user has both a followers and a following groups, I've created a GroupMyTwitter domain.
What I don't understand, is the logic behind this. My GroupMyTwitter domain is like this :
class GroupMyTwitter
{
String name;
static constraints = { name blank : false; }
static hasMany = [users:UserMyTwitter];
static belongsTo = [owner:UserMyTwitter];
}
Then every time I create a user I also create two groups associated to him :
GroupMyTwitter followers = new GroupMyTwitter (
name:"followers",
owner: user).save(flush: true, failOnError: true)
// And same for followings
Now I simply wonder... how can I access these groups to get the followers/ings count, add or delete some?
Thanks for your help.
Based on the hasMany and belongsTo variables gorm automatically creates some instance fields for you:
static hasMany = [users:UserMyTwitter];
This will create a field users of type Set inside GroupMyTwitter.
You can access this Set like any other field:
followers.users.add(userA) // add a user
followers.users.remove(userB) // remove a user
followers.users.size() // number of users
// don't forget to save the group after you modfied the `users` collection:
followers.save(failOnError: true)
Depending on your needs it might be useful to use a List instead of a Set:
class GroupMyTwitter {
List users
static hasMany = [users:UserMyTwitter];
...
}
This causes Gorm to use a List for the users collection instead of a Set.
A List has a defined order and allows you to access certain elements by index:
UserMyTwitter user = followers.users[4] // get the 5th user
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*.
I have User class:
class User {
static hasMany = [ project: Project ]
}
and Project:
class Project {
static hasMany = [ users : User ]
static belongsTo = User
}
Anywhere in my code I can do this :
user.project
will return something like :
[project name]
I need a way to delete this relationship for any User. How can I do that? I can find a user project using dynamic finders, criteria query so on, but how do I remove that relationship from a user instance?
Very new to Grails.
Thanks in advance.
Use removeFrom. Example:
user.removeFromProject(project)
In many-to-many relationships, you should manage the associations from the owning side: the one that is the target of the belongsTo.
Note that it would probably be more clear to name the Project association "projects" instead of "project", since it's a many-to-many relationship.