Wondering if "belongsTo" is write way to represent an ownership relationship where there is always a parent object, but the parent may switch.
ie if owner domain is
class Owner {
String name
}
Should House be:
class House {
String address
Owner owner
}
or
class House {
String address
static belongsTo = [owner: Owner]
}
What I want to achieve is bi-direction 1:1 where I can either access owner.house or house.owner and ability to change the owner without without deleting the old owner.
without deleting the old owner. ?
So you have two choices - by far the easiest and where your current method is actually wrong should be Should House be: maybe this?
class House {
String address
static hasMany = [owner:Owner]
Owner currentOwner
}
With the relationships as it is, you are saying a house has many owner's. So owner1 owner2 .. and it also has a current Owner which is Owner itself.
Each time you add a new entry you add it to the owner collection so house.addToOwner(owner) and you then set the last/latest update of currentOwner=owner.
If you want to navigate throw both entities, and the relation is 1:1 you can use hasOne
class Owner {
String name
static hasOne = [house: House]
}
class House {
String address
static belongsTo = [owner: Owner]
}
Related
I am having some issues with setting relation among two classes. I have 2 classes, Student:
class Student {
String name
Guardian father
Guardian mother
Guardian local_guardian
}
and Guardian:
class Guardian {
String name;
static hasMany = [children:Student]
static mappedBy = [children:'father']
}
Here, I used mappedBy to map Guardian object to father property . Unless mappedBy, I was getting error telling, should use mappedBy with any of the 3 Student class property.
I tried this query to enter some sample data
new Student(name:"John", father: new Guardian(name:"Michael").save(),
mother: new Guardian(name:"Mary").save(),
local_guardian: new Guardian(name:"James").save()).save(flush:true);
The data is getting saved successfully but my problem is, Since I used mappedBy with 'father' property, I am able to use Guardian.children only with that father object.
when I try to get list of children with mother and local_guardian object,
(eg: mother.children) getting null result.
I tried by adding with addTo on the many side like
Guardian.findByName("Mary").addToChildren(
Student.findByName("John")).save(flush:true);
and tried accessing
Guardian.findByName("Mary").children
Here, I got the result , but it moved the child from father to mother object, and no longer able to access father.children
How will I solve this scenario?
What I am trying to achieve is, I should be able to get list of children from all 3 of the Guardian object . Here One Student object is pointing to 3 Guardian objects (father, mother, local_guardian) . So I should be able to get the list of children by
father.children
mother.children
local_guard.children
How will I set the proper relation among these classes to solve my problem?
If you want to implement this relation using hasMany then you will need to have three mappedBy in Guardian class.
static hasMany = [children:Student, motherChildres:Student, localGuardianChildrens:Student]
static mappedBy = [children:'father', motherChildrens:'mother', localGuardianChildrens: 'local_guardian']
But this does not look good, instead you can implement a relation using a middle level domain class and add addToChildren and getChildrens methods in Guardian class like below.
class GuardianChildren {
Guardian guardian
Student student
constraints {
student unique: ['guardian']
}
}
Guardian {
void addToChildrens(Student child) {
new GuardianChildren(guardian:this, student:child).save()
}
#Transient
List<Student> getChildrens() {
return GuardianChildren.findAllByGuardian(this).children
}
}
Student {
#Transient
Guardian getMother() {
//find guardin children where guardian type is mother and children is this student
}
#Transient
Guardian getFather() {..}
}
Remove hasMany from Guardian and father/mother properties from Student. You will also probably need a type field in Guardian to specify if this is mother/father etc
You likely want to use hasMany and belongsTo, then to define the guardian you might want to use something like a father, mother, localGuardian properties in the guardian object. With such a relationship you can then use transients to define the set of children and mother / father.
So for example
class Student
{
String name
Guardian local_guardian
static belongsTo = [primaryGuardian: Guardian]
static transients=['mother', 'father']
//define the transients
def getMother(){
if(primaryGuardian.type == 'mother') {
return primaryGuardian
} else {
return primaryGuardian.spouse
}
}
//do something similiar for getFather
}
Class Guardian
{
String name
String type
Guardian spouse
static hasMany = [children:Student, localGuardianStudents: Student]
}
Please note that this is just example code and may contain errors as I didn't test it.
So you can then create a guardian, and then add children by calling
guardian.addToChildren(child)
Anyways, this will let you get the children of a guardian by calling guardian.children, it lets you get the primary guardian (either the mother or father) of the child by calling child.primaryGuardian, and it lets you get the mother or father by calling child.mother without the need to add special types in there.
You will want to make sure that you modify the constraints here, so that the spouse could be null. Furthermore relationships of this nature can sometimes get tricky when creating them causing errors relating to missing ID numbers when you are trying to save, so you want to be sure that you make sure that both sides of the relationship are defined when you create and modify these objects.
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.
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*.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Grails/GORM: The meaning of belongsTo in 1:N relationships
I have 2 domain class with belongsTo association
class Teacher {
String name
String department
}
class Address {
String line1
String line2
// Teacher teacher //this line is commented.
static belongsTo = [teacher: Teacher]
static constraints = {
}
}
What is the advantage i get when i make Address belongsTo Teacher
do i need to declare teacher object reference in Address class (see the commented line in Teacher class)
The goal to have the belongsTo clause is to have bi-directional access from one class to the other. See Documentation of belongsTo.
You can omit the second declaring of teacher (you commented out).
So it should look like this:
class Teacher {
String name
String department
Set<Address> adresses = new HashSet<Address>() // here you could set a specific list/set data holder
static hasMany = [adresses:Address]
}
class Address {
String line1
String line2
static belongsTo = [teacher: Teacher]
static constraints = {
}
}
Here you have a one-to-many associaton, where both classes have access to each other. If you remove the belongsTo clause you can not access the teacher object from the adress object. This is also reflected in the database.
Goal of belongsTo isn't making the relations bidirectional - The goal is to specify which side of the association takes the ownership and to define the behavior of cascading save and delete operations
Read this documentation it explains every thing you need to know about belongsTo.
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.