Grails relationship reference despite having a belongsTo - grails

Let's say an Owned domain class belongs to an Owner domain class by having this declaration in its body:
static belongsTo [ Owner ]
Why then in some cases do I still see the Owned domain class also having a property or field like reference to the Owner domain class like
Owner owner
despite having the belongsTo clause in its body? Wouldn't the belongsTo declaration take care of the needed reference in this case?

The combination of
static belongsTo = [ Owner ]
and
Owner owner
is essentially the same as
static belongsTo = [owner: Owner ]
because using the map form triggers (via an AST transformation) the creation of a property of type Owner with name owner.
My preference is to use the single statement however because it's the standard way to declare a bidirectional one-many and the other way feels like a side effect.
One reason that using the simpler form of belongsTo and declaring the owner property is when you have multiple parent domain classes, but some are bidirectional and some aren't, e.g.
static belongsTo = [Owner, OtherClass]
Owner owner
This way you make Owner/Owned bidirectional, but leave the OtherClass relationship unidirectional.

Related

Grails: Simple hasMany relation create more tables than necessary

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.

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 belongsTo relationship mechanism

In a Grails relationship when an Owner domain class owns an Owned domain class, I've seen this declared two different ways in the Owned domain class:
static belongsTo [ owner : Owner ]
and sometimes as
static belongsTo [ Owner ]
what is the difference between these two other than the syntax?
The difference is being able to indicate the name of the owned by property. In the second case it's going to assume the bean name convention of the class owner where as the first you are being explicit about the name of the property.
It's about flexibility. The first option is there if the second doesn't do what you intend or want.
The first is bidirectional, since you have an instance of Owner defined in your class. The key of that map is typically the lowercase name of the domain class, but it can be any legal variable name. An AST transformation adds a property to your domain class (you can see this by decompiling the .class file), basically
Owner owner
or
Owner theOwner
if you had declared the belongsTo as
static belongsTo = [theOwner: Owner]
Don't add this yourself though - it's already there in the bytecode.
This is similar to declaring a hasMany, where the key of that map defines a collection (by default a Set but optionally a List). E.g. declaring
static hasMany = [owned: Owned]
creates the equivalent of
Set<Owned> owned
in the bytecode.
The second isn't bidirectional since there's no direct way to get to the owning instance.
Directionality has an impact on the table structure. In the first, you get what you probably expect - an owner_id column in the Owned domain class table which is a foreign key to the Owner domain class table. But in the second, there isn't a domain class property to associate with a foreign key, so in that case a third table is created to be the join table, similar to what happens for a many-to-many relationship.
I find that the schema-export script is very helpful for stuff like this. For each variant of the syntax, run
grails compile
grails schema-export
and view the contents of target/ddl.sql to see the resulting table structure for your domain classes.
it's as simple as that:
if you define the
static belongsTo = [ owner : Owner ]
then you can can access the owner as a variable: obj.owner. If you write:
static belongsTo = [ Owner ]
then you can't (you will get NoSuchPropException I guess).
In both cases the foreign-key relation is created

Is there anyway to perform a "deep save" in Grails?

In my service I create a "root" object which has associations to many objects which in turn have associations to many more objects and so on. Once the root object is completely built and ready to be saved I would like to call save on the root object and have all associated objects all the way down be saved as well. Right now I have a recursive method called deepSave which does this. Is there a better way?
If you use belongsTo GORM automatically defines the cascading for you. This means: If A belongsTo B then A will be saved when B is saved. However, it is possible to define cascading without using belongsTo (if this does not fit to your domain model):
class Author {
static hasMany = [books: Book]
static mapping = { books cascade: 'all-delete-orphan' }
}
You should have a look at the cascade property provided by GORM. Additionaly the hibernate documentation provides more detailed information.

how to create a reference relationship in groovy domains?

i just wanted to make a drop down box appear on the view page of my main domain.
I tried doing
static hasOne = [sex: Sex, accountType: accountType]
and I did this on the main domain but it would give me an error that the domains I wanted to have a reference with are not bidirectional. so i just tried to put a reference on the reference domains of my main domain which now made the reference domain like the accountType have a field of a specific.
I was wondering how can I just make it like a one way reference?
To make it a one-way reference, don't use the hasOne connection.
So, your class would look like this instead:
class MyClass {
Sex sex
AccountType accountType
}
hasOne and it's brethren indicate who "owns" a bi-directional relationship, so if you are only going one way, you don't need to use them.

Resources