Behaviour of belongsTo - grails

What is the difference between
static belongsTo [author:Author]
and
static belongsTo = Author
Lets consider two domain class.
Class Author{
String name
}
Class Books{
String name
static belongsTo = Author
}
When static belongsTo = Author is kept in Books domain, it have no effects on db. However, static belongsTo = [author : Author] creates a backreference to Author class and also there is author_id column in db. So, what actually using static belongsTo = Author alone does.
This is expalined in grails docs(http://grails.github.io/grails-doc/latest/ref/Domain%20Classes/belongsTo.html).
Also, what is the difference between using following two :
Class Books{
String name
static belongsTo = [author : Author]
}
Class Books{
String name
Author author
}
static belongsTo = [author : Author] is used only for cascading purposes, Is it true or does it have different use cases.
Can anyone explain these in detail without relating it to hasOne or hasMany. Thanks in advance.

Using belongsTo without a back-reference is necessary for many-to-many associations. For example, lets assume you have the following domain classes:
class Book {
String name
Author author
static hasMany = [categories: Category]
}
class Category {
String name
static hasMany = [books: Book]
}
If you try to use them as-is you'd get an exception like this:
No owner defined between domain classes [class Book] and [class Category] in a many-to-many relationship. Example: static belongsTo = Category
The solution is to make one of the domain classes the owner of the many-to-many association. Using my example, I think it makes more sense to make the Category the owner. However, a back-reference would not work because there could be multiple Categorys. So, this is where a belongsTo without a back-reference comes in:
class Book {
String name
Author author
static hasMany = [categories: Category]
static belongsTo = Category
}

If you use static belongsTo = [author: Author] then a property named author of type Author is added to the class as a back reference. With static belongsTo = Author that does not happen.

Related

grails: multiple belongsTo with back reference

Is it possible to have a domain class that belongs to multiple domain classes with back reference? For instance:
class Person {
List<Book> books
static hasMany = [books: Book]
}
class Organization {
List<Books> books
static hasMany = [books: Book]
}
class Book {
def owner // what's the type?
static belongsTo = [Person, Books]
}
A Book can belong to a Person or an Organization, but not both.
Person and Organization have separate sequence IDs.
The solution I came up with is:
class Book {
Long ownerID
String ownerClass
static belongsTo = [Person, Books]
static transients = ['owner']
static constraints = {
ownerId(nullable:false, blank:false)
ownerClass(nullable:false, blank:false)
}
public BookOwner getOwner() {
grailsApplication.getArtefact("Domain", ownerClass)?.getClazz()?.get(ownerId)
}
}
where BookOwner is an Interface implemented by Person and Organization. So calling a bookInstance.owner will return a Person or Organization instance, both BookOwner.
My solution works well, but it doesn't feel right - a sure sign that I am not fully understanding what I'm doing. What's the best way to implement this? Should I completely give up on having the extremely convenient back reference?
Thank you
I guess, you should have made Owner superclass. Grails will create Owner table with field class meaning child class names (in your case: Person, Organization).

belongsTo array plus hasMany ownership

I have a Grails class that both has got a many-to-many relationship (with the other side being the owner) as well as a n:1 relationship.
I could not find an answer on the web how to put the ownership into the belongsTo clause.
This is the code:
class PanelType {
static hasMany = [elements: LabValueType]
}
class LabValueType {
static belongsTo = [labUnit: LabUnit]
// This is what would be needed to have a bidirectinal n:m relationship
// belongsTo = PanelType
// static hasMany = [panelTypes: PanelType]
}
If I leave it like this, the application builds the database correctly, but I won't be able to navigate from LabValueType to PanelType.
I found one answer (from 2008!) that said I should write:
static belongsTo = [PanelType, LabUnit]
BUT this way, the field lab_unit_id is not created in the database, so it does not seem to be correct.
I have found that I can work around this problem by declaring the relationships like this:
LabUnit labUnit
static belongsTo = PanelType
static hasMany = [panelTypes: PanelType]
But somehow it is not really 100% satisfying.

Grails Domain Class : hasOne, hasMany without belongsTo

I am new to Grails.
Can I use "hasOne" or "hasMany" without using "belongsTo" to another domain-class?
Thanks in advance.
Yes, you can. See examples in Grails doc: http://grails.org/doc/2.3.8/guide/GORM.html#manyToOneAndOneToOne
hasMany (without belongsTo) example from the doc:
A one-to-many relationship is when one class, example Author, has many
instances of another class, example Book. With Grails you define such
a relationship with the hasMany setting:
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
}
In this case we have a unidirectional one-to-many. Grails will, by
default, map this kind of relationship with a join table.
hasOne (without belongsTo) example from the doc:
Example C
class Face {
static hasOne = [nose:Nose]
}
class Nose {
Face face
}
Note that using this property puts the foreign key on the inverse
table to the previous example, so in this case the foreign key column
is stored in the nose table inside a column called face_id. Also,
hasOne only works with bidirectional relationships.
Finally, it's a good idea to add a unique constraint on one side of
the one-to-one relationship:
class Face {
static hasOne = [nose:Nose]
static constraints = {
nose unique: true
}
}
class Nose {
Face face
}
Yes you can, but it behave differently
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
}
In this case if you delete Author the books still existing and are independent.
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
static belongsTo = [author: Author]
}
In this other case if you delete the Author it will delete all the books pf that author in cascade.
Many-to-one/one-to-one: saves and deletes cascade from the owner to the dependant (the class with the belongsTo).
One-to-many: saves always cascade from the one side to the many side, but if the many side has belongsTo, then deletes also cascade in that direction.
Many-to-many: only saves cascade from the "owner" to the "dependant", not deletes.
http://grails.org/doc/2.3.x/ref/Domain%20Classes/belongsTo.html
yes very easy like a class defintion but only specify hasMany but no need for hasOne
class Student {
String name
User userProfile
static hasMany =[files:File]
}
class User {
String uname
Student student
}
class File {
String path
Student student // specify the belongs to like this no belong to
}
Done!!

Command Object and hasmany

I'm trying to use the commandObject to validade my data when I submit my form. Can I validate a hasMany relation in commandObject. My cenario is something like this.
Tow simple classes whith hasMany relationship:
class Book{
String nameBook
}
class Author{
String nameAuthor
static hasMany = [books:Book]
}
Simple commandObject with hasMany that i want to validate when submit form.
#grails.validation.Validateable
class MyValidateCommand{
String nameAuthor
static hasMany = [books:Book]
static constraints = {
nameAuthor nullable:false
books nullable:false
}
}
Ps: I know that this commandObject is wrong, it don't compile. But can I do something like this ???
hasMany in GORM is used for association in Domain objects. In case of command objects it will be a lucid approach to have different command objects for each domain (for example: AuthorCommand and BookCommand) and the command object would look like:
import org.apache.commons.collections.list.LazyList
import org.apache.commons.collections.functors.InstantiateFactory
//Dont need this annotation if command object
//is in the same location as the controller
//By default its validateable
#grails.validation.Validateable
class AuthorCommand{
String nameAuthor
//static hasMany = [books:Book]
//Lazily initialized list for BookCommand
//which will be efficient based on the form submission.
List<BookCommand> books =
LazyList.decorate(new ArrayList(),
new InstantiateFactory(BookCommand.class))
static constraints = {
nameAuthor nullable:false
books nullable:false
//Let BookCommand do its validation,
//although you can have a custom validator to do some
//validation here.
}
}
Not sure why don't you can try like(normal hibernate hasMany declaration)
class MyValidateCommand{
String nameAuthor
Set<Book> books= new HashSet<Book>();
static constraints = {
nameAuthor nullable:false
books nullable:false
}
}

No owner defined between domain classes: many to many relationship

These are my domain classes:
class Game {
static hasMany = [players: User]
static belongsTo = [owner: User]
}
class User {
static hasMany = [games: Game]
}
If I try to use them as they are I get No owner defined between domain classes. So I need to set the owner of the relationship. Adding static belongsTo = Game to User causes Domain classes cannot own each other in a many-to-many relationship.
The only other option I can think of is to add static belongsTo = User to the Game class but I already have a belongsTo there.
How do I model this?
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
class User {
static hasMany = [games: Game]
}
You will have to specify one side of the relationship, as the owner, by doing this you will make User domain class as the owner of the many to many relationship.
The belongsTo field controls where the dynamic addTo*() methods can be used
from. we’re able to call User.addToGames() because Game belongsTo
User. we can’t call Game.addToPlayers().
Try this:
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
maybe it would be better not to use "belongsTo" at all? I mean using simple field reference like
class Game {
User owner
static hasMany = [players: User]
}
FYI,
I would be careful with using "owner" field name, it might cause problems when used somehow in a closure which has its own "owner" reference (e.g. in criteria builder)
I know it caused problems back in grails 1.3.X, I don't know if it's still the case
try this:
class Game {
User owner
static hasMany = [players: User]
static belongsTo = User
}
class User {
static hasMany = [games: Game, owns: Game]
static mappedBy = [games:'players', owns: 'owner']
}
this settings work for me. And here is a good thread for mappedBy: GORM mappedBy and mapping difference

Resources