Grails: Simple hasMany relation create more tables than necessary - grails

Hi I have a simple problem.
My domain class is like this:
class Example {
long seq
hasMany = [example_array: ExampleData]
long count
}
class ExampleData {
String type
long description
static belongsTo = Example
static constraints = {
}
}
This results in 3 tables, like a many to many relation.
Why is this?
Thanks

The reason for the extra table is that you've modeled the relation only in one direction - an Example can access its ExampleData instances via the example_array Set that's added to your class bytecode because of the hasMany property, but an ExampleData instance has no way to reference its owning Example.
You added a belongsTo property, but only specified the class name. That's sufficient to configure ownership, cascaded deletes, etc. but doesn't provide a property in the class to access the Example instance.
If you change it to the other supported syntax it will work as you expected:
static belongsTo = [example: Example]
Here example will end up being the name of an Example property (and you can change it and/or example_array to any valid property name), which is basically the same as declaring
Example example
Now that both sides can access the other, the relationship is bidirectional and you no longer need the third table. That's because a 1-many is typically implemented using a foreign key in the child table, in this case in the table for ExampleData that points to the table for Example. That wasn't possible without a property in the class to wire up to that column, so the join table was necessary.

I believe that you have to map the BelongsTo, like this:
static belongsTo = [example:Example]
Hope it helps :)

From the definition of hasMany Grails will, by default, map this kind of relationship with a join table.That join table is the 3rd table you mentioned.No need to worry about that.

Well the one-to-many relationship is constructed by having additional table (i.e. Example_ExampleData) containing two columns each id fields from tables of the entities forming the relationship(i.e. Example and ExampleData).
The newly added table is child to parent tables – Example and ExampleData.
So in your case when you run your application the 3rd table gets created by Grails by default as your table relationship falls under the one-to-many relationship.

Related

Issue on Grails GORM domain classes with "soft" joins

I have mapped two tables on Domain classes, say:
Parent table that hasMany of the table Child.
Child table that belongsTo a table Parent.
I want point out that there is no specific foreign keys explicitly declared on the database, rather it is declared on the GORM's mapping. But here's the catch: There are special types of Child that are orphans- that is, doesn't have their Parent table counterparts. Everytime I access these orphans via a valid Child.findById(), an error shows:
Message: No row with the given identifier exists
that is not present when accessing a non-orphan Child. I had marshalled these Domain tables already in such a way that everytime a Child is parsed as JSON, it will have a property called parents which is an array of Parent and the other way around. It is already working- except for these orphans' case.
How should I fixed this? Should I remove their GORM join, since they are not actually joint on the database side?
I'm assuming you have domain classes that look like this:
class Parent {
static hasMany = [children: Child]
}
class Child {
static belongsTo = [parent: Parent]
}
That's a bi-directional one-to-many association. GORM expects the child table to contain a foreign key to the parent, and the child can only exist if it has a parent.
One way to allow orphan children is do to as you suggested: remove the gorm associations. Another way is to remove the belongsTo to create a uni-directional association. That way a child can exist without a parent.

Is there any difference between "belongsTo" constraint and just being a field in Grails?

I have created Child domain and made 2 parents to it. One parent I declared as a field. And another parent I declared with the help of belongsTo constraint.
package multipleparentsgrails
class Child {
Parent2 parent2
static belongsTo = [parent1: Parent1]
static constraints = {
}
}
Is there any difference between these ways?
How to eliminate differences? Can I have both belongTo and a member? Can I add cascading having a member?
belongsTo plays significant role in parent child relationship. Here the class specified in belongsTo is the Parent / Owner of the relationship.
Following could be some comparison in normal has a and belongs To:
belongsTo marks the referenced class as Owner of the relationship while same is not true in case of has a
You don't need to worry about hibernate related cascading as relationship automatically will handle that i.e. you may specify cascade type but need not to give implementations otherwise in case of has a you have to use GORM DSL like stuff.
Last but not least belongsTo also makes it mandatory to specify relationship owner while in case of has a constraints are the barriers.
Last but not least it might also make difference in gsp scaffolding as well but not sure about it.
Hope it Helps!
Yes, belongsTo defines cascading. If parent1 is deleted, so is child since it belongsTo parent1. If parent2 is deleted, Grails won't delete child automatically for you.
So, in this case, stating that a child belongsTo a parent wouldn't be very children-friendly :-)
You can define belongsTo in a few different ways, which allows you to define it on separate fields or to declare new fields. See the Grails documentation for further details, they have good examples of its use.

Grails: Delete relation Domain

I want to asked about my project.
I Have Two Domain like this
I suggest you to look in the GORM documentation. You have some ways to declare your relationship between classes, and depending on them the delete will be cascade or not.
This behavior is explained in "6.3.3 Understanding Cascading Updates and Deletes".
Whether it is a one-to-one, one-to-many or many-to-many, defining
belongsTo will result in updates cascading from the owning class to
its dependant (the other side of the relationship), and for
many-/one-to-one and one-to-many relationships deletes will also
cascade.
So you should consider declaring hasMany and belongsTo, to enable the cascading deletes.
class User {
// Group details should not be referenced here
}
class Group {
String Name
String Description
GroupDetails gd
}
class GroupDetails {
User user
static belongsTo = [group:Group]
}
In this case if Group will have a child GroupDetails then when you delete Group, child entity(ies) will also be deleted.
Have a look at first example in grails docs: http://grails.org/doc/2.2.x/ref/Domain%20Classes/belongsTo.html
Also as Sérgio Michels there are more ways to make it work.
example: https://github.com/aprudnikovas/testGrailsOneToOneCascade

One-to-many relationship not working as expected

I'm having some problems getting a one to many relationship in grails working properly.
I have a person instance and this person has relationships to other persons. This relationship is defined in a relationship object.
The relevant code is as follows.
class Person {
static hasMany = [relationships:Relationship]
String name
}
class Relationship {
Person relationShipTo
// Enum containing married, living together, parent etc.
RelationshipType typeOfRelationship
}
Now what i want is a one to many reference to that relationship to be persisted but what happens in grails is that it seems to think the relationShipTo instance is refering back to the Person that has this relationship with someone else, and not to the other person.
So a person has a reference to a relationship, and that relationship has a type and a reference to the person with whom you have a relationship with.
I'm not able to change the domain model for this. Is there any way of accomplishing what i want?
What is currently happening if i use the generated views and controllers for the Relationship and try to create a relationship with a type and a person it is refering to, only the type is persisted and the person is ignored. When i then try to add it to the person in the persons edit or create page, all the relationShipTo properties of the relationships i add is saved with the id of the person.
Hopefully what i wrote is understandable.
Finally got it working.
Had to add a static mappedBy =[relationship: 'belongsTo'] to person
and a static belongsTo = [belongsTo: Person].
Not exactly how i wanted it but it works and is an ok compromise

Grails - Need to restrict fetched rows based on condition on join table

I have these two domains Car and Driver which have many-to-many relationship. This association is defined in table tblCarsDrivers which has, not surprisingly, primary keys of both the tables BUT additionally also has another boolean field deleted. Herein lies the problem. When I find/get query on domain Car, I am fetched all related drivers irrespective of their deleted status in tblCarsDrivers, which is expected.
I need to put a clause/constraint to
exclude the deleted associations from the
list of fetched records.
PS: I tried using an association domain CarDriver in joinTable name but that seems not to work. Apparently it expects only table names, not maps.
PPS: I know its unnatural to have any other fields besides the mapping keys in mapping table but this is how I got it and it cant be changed.
Car domain is defined as such -
class Car {
Integer id
String name
static hasMany = [drivers:Driver]
static mapping = {
table 'tblCars'
version false
drivers joinTable:[name: 'tblCarsDrivers',column:'driverid',key:'carid']
}
}
Thanks!
I know its unnatural to have any other
fields besides the mapping keys in
mapping table but this is how I got it
and it cant be changed.
This is not at all unusual. If you want to store properties about the relationship, this is the obvious solution. You should reinstate your association domain CarDriver which has a deleted property in addition to a relationship to Car and Driver, and you should then be able to write a query which excludes the deleted drivers.
A comprehensive example of how to define such a mapping is provided here.

Resources