OneToMany association in grails domain classes - grails

I want one to many association between the Person and Address domain class which will be more like :
create table person (id bigint),
version bigint not null,
primary key (id))
create table address (id bigint),
person_id bigint not null,
primary key (id))
I tried to establish oneToMany Relation between these two tables so that one person can have n number of addresses.
class Person{
static hasMany = [
addresses: Address
]
}
class Address{
Address address
}
This is how I think it should work, i tried serveral other option, but none worked as wanted. Either I get an crosstable or an error when starting the application.
Thanks for help

You need to do establish one-to-many relationship between the Domain class Person & Address as given below-
Person Domain class
class Person{
static hasMany = [addresses: Address]
}
Address Domain class
class Address{
static belongsTo = [person : Person]
}
Please go through the grails documentation for gorm to understand the
domain class relationships in depth.

Related

Grails 3 hasOne nullability issue

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

Grails hasOne vs. belongsTo

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.

Creating one-to-many & many-to-many for same domain class in grails

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.

Grails domains inheriting abstract classes hasMany

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.

Child class object can not delete

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

Resources