So I'm attempting to let 2 domains inherit from a single domain.
abstract class Pet {
Nose nose
static hasMany = [legs: Leg]
}
class Dog extends Pet {
static hasMany = [friends: Friend]
}
And I'm getting an error:
Caused by: org.codehaus.groovy.grails.exceptions.InvalidPropertyException: No property found for name [legs] for class [class animals.Dog]
Any ideas? Is there something I have to do to combine the hasManys?
I tried replicating the problem and I did not get an InvalidPropertyException, but the database schema that was generated was missing the 1:m relationship between Dog and Leg.
I believe the problem is related to Pet being an abstract class. If the Dog class inherits Set legs from Pet, then in order to persist the Leg instances to the database, the underlying Leg table needs to have a foreign key of pet_id**. Since Pet is an abstract class, a table is not created for it and therefore no id column. Therefore, no foreign key can be created in the dependent class, Leg.
Making the Pet class a concrete class (moving it to grails-app/domain and removing the abstract keyword), means that a table with an id field will be created. And in the Leg table, a pet_id column can/will be created that Hibernate will use to persist/retrieve the Set legs.
** (or an associative entity table, such as pet_legs, would need to have the foreign key)
Making the Pet class concrete, however, will cause all the sub-classes of Pet to be stored into that table, so if you want each sub-class to have its own table, you could add:
static mapping = {
tablePerHierarchy false
}
to the Dog class, which will create a Pet, Dog, etc table in the db.
You're missing a couple of things:
GORM won't generate table relationships for an abstract class
static fields/methods are not inherited. They belong to the class, not to the object references
So you have to change the code to one of the following:
abstract class Pet {
Nose nose
}
class Dog extends Pet {
static hasMany = [legs: Leg, friends: Friend]
}
or
abstract class Pet {
Nose nose
static hasMany = [legs: Leg]
}
class Dog extends Pet {
static hasMany = [friends: Friend] + Pet.hasMany
}
Yes the second approach works because you can initialize static members of a class by another static classe's static member.
Related
To create one-to-one relationships in Grails I can do:
class Person {
static hasOne = [address: Address]
}
In this case the Address table has the key to its person. I could also do:
class Address {
static belongsTo = [person: Person]
}
This gives the same result.
What is the difference between my two samples using hasOne and belongsTo?
hasOne indicates that there is a bi-directional one-to-one relationship where the child table has the parent's foreign key, as in your example.
belongsTo is used to control cascades by indicating that the class belongs to the specified class. In your example, deleting a given Person would cascade the delete to any associated Addresses.
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 have some domain class Incident,Problem, Category, Impact, Urgency etc.
Class Incident
{
Category category
String subject
Impact impact
}
Class Problem
{
Urgency urgency
Category category
String title
}
Class Category
{
String categoryName
String description
}
now, some rows are inserted into this class. now if I am deleting category it throws error like 'grails cannot delete or update a parent row'..
so what I have to do for deleting?
The problem is - you have reference to Category in Incident and Problem classes, so database tables for those classes will have Foreign key on category table, so you can not delete a category untill you either remove those incidents/problems or update those incidents problems and set category to null (you will have to make them as nullable in domain constraints)
So either you do
Problem.executeUpdate('update Problem p set category = null where category = ?', [category])
Same for incidents
Or you can model your domain classes using belongsTo and hasMany and grails will handle every thing automatically
Some thing like
class Problem {
static belongsTo = [category:Category]
}
class Category {
static hasMany = [
problems: Problem
]
static mappings = {
problems cascade: "all-delete-orphan"
}
}
I would prefer to manage relationships using belongsTo, hasMany, hasOne rather then just using references, it expresses the model better.
It depends on your domain model as well, in your business can problems, incidents exist without a category ! or they must belong to some category. If your answer is first option, your dont want to cascade delete, but update those incidents/problems with null category, if your answer is second option - you needs cascade all-delete-orphan
How your Category looks like, is it belongsTo Incident domain class,if category belongs to some domain class you can not delete it.
Ref : See here
In Grails belongsTo allows one domain class to establish a cascading relationship with another domain class. There are two styles of relationships when using belongsTo: Reference and No Reference. Reference creates a property on the owned object while No Reference merely establishes an invisible GORM relationship.
Example parent domain-class:
class Car {
Engine engine
}
belongsTo without Reference property:
class Engine {
static belongsTo = Car
}
belongsTo with Reference property:
class Engine {
static belongsTo = [car:Car]
}
Not to hard right, however the trouble for me starts when we start using multiple belongsTo references:
belongsTo with multiple back references:
class Engine {
static belongsTo = [car:Car, user:User]
}
multiple belongsTo relationships without property references:
class Engine {
static belongsTo = [Car, User]
}
Here's the problem, how do I mix the two above styles?
Say I want a property reference for the User but not for the Car, how would I write that belongsTo call?
Any information on how to mix No Reference relationship links with Reference property in a single domain class would help.
Links:
Using Grails Object Relational Mapping (GORM)
belongsTo - grails.org
This question reposted by me on the official Grails forum
class Engine {
User user
static belongsTo = [Car, User]
}
That said, I always use the map (reference) syntax over the list (no reference) syntax because I like mine to be bi-directional.
I need a way to be able to have a domain class to have many of itself. In other words, there is a parent and child relationship. The table I'm working on has data and then a column called "parent_id". If any item has the parent_id set, it is a child of that element.
Is there any way in Grails to tell hasMany which field to look at for a reference?
This is an example of what you are looking for (it's a snippet code I am running and it generates column parent_id). I don't think you need SortedSet:
class NavMenu implements Comparable {
String category
int rank = 0
String title
Boolean active = false
//NavMenu parent
SortedSet subItems
static hasMany = [subItems: NavMenu]
static belongsTo = [parent: NavMenu]
}
Furthermore, you can give name to the hasMany clause using the Mapping DSL, which is explained at http://grails.org/GORM+-+Mapping+DSL