Setting metaClass property on domain object - grails

Any reason not to use metaClass on domain objects? as in
domainObjectInstance.metaClass.dynamicTransientGreeting = "Hello"
Will this mess with hibernate at all?

It won't mess with Hibernate at all since it won't be seen by Hibernate. GORM only maps "real" properties to Hibernate properties.
That's why the id and version columns and the collections that are generated from hasMany declarations (e.g. the users collection generated by static hasMany = [users: User] are added to the actual bytecode using an AST. If they were added just to the MetaClass they wouldn't be seen and wouldn't be persistent.

Related

Grails domain classes static properties hasOne, hasMany and belongsTo

I am new to Grails and I would like to know what impacts exist on generated code, db schema, GORM, etc. when using Grails' predefined static properties on domain classes like hasOne, hasMany and belongsTo.
For example, would hasOne force a singleton pattern somewhere?
Taking a quick look at both generated code and database, I didn't find many clues.
belongsTo forces a save of the child class when saving the parent class
hasOne creates a one-to-one / one-to-many mapping in the DB (no association table)
hasMany is used for one-to-many (is in one of the classes) / many-to-many (if in both classes, with association table)

hasMany vs having a collection of an object in grails

Is there a difference between using hasMany
static hasMany = [objects:Object]
and adding a collection of object
Set objects
There is definitely a difference between using:
static hasMany = [objects:Object] and List objects
static hasMany = [objects:Object] is stored in a java set there you cannot have duplicate objects. Furthermore, the objects will not be in order of insertion.
List objects is a typical java list which will allow duplicates as well as be able to maintain order.
I believe there are more differences but I am just posting the differences I am aware of.

Grails hasOne association

What is the difference between these 2 hasOne syntax ?
class Project {
.......
............
static hasOne = Employee
// static hasOne = [employee:Employee]
}
I have noticed that the first one creates a many-to-many relationship(3 tables) but it should be many-to-one(2 tables) as in the Employee class I have:
static hasMany = [projects:Project]
The second one works fine:
static hasOne = [employee:Employee]
I am using Grails 2.2.0 and I even tried in Grails 2.0.3 but the result is same.
Thanks
I don't think that the 1st variant makes any sense at all. You could define a belongsTo back-ref without specifying a field for that, and this could be used for cascading things for example.
The case with hasOne is quite the opposite: you want to have an explicit one-to-one, which makes it logical to specify the reference explicitly:
static hasOne = [employee:Employee]
The most common case to use hasOne is when you want to have one-to-one relation, but you don't want to modify the domain class you are referencing, so that you don't have to introduce more complexity and/or migrate the old table.
To my mind, the 1st variant is useless and doesn't produce an error due to... lack of GORM developers time? ;)

Grails/GORM default fetch strategy: When to set fetchMode to "eager"? (eager vs. lazy)

What are some general guidelines on when to set fetchMode to "eager" in a domain class? Pros and cons of fetchMode "eager" vs. the default "lazy"?
Please include some specific examples/use-cases showing when to use "eager" (fetchMode=eager), and when not to (fetchMode=lazy).
Basically lazy loading has more benefits than the eager alternative (performance, use of resources) . Since it's the default grails setting for all relations (since Grails 1.1) you should generally not configure it for eager fetching, unless you experience certain issues. Such as:
Sharing a domain instance accross different hibernate sessions (eg. when putting a domain class instance into the http session scope and accessing properties from it - such as a User)
Getting LazyInitializationException when accessing domain class instances in layouts/views
When you're sure, you will access a certain relation property everytime (or most of the time) when an instance is fetched, it would also make sense to configure this relation for eager fetching.
Eager fetching can be quite dangerous when dealing with huge databases. Imagine a Domain class like this:
// really bad example
class TreeNode {
String name
TreeNode parent
static hasMany = [ childNodes: TreeNode ]
static mapping {
parent lazy: false
childNodes lazy: false
}
}
when you read any of the TreeNode instances, it will automatically pull all other instances of the domain class from the database into your memory. When there are enough instances, you'll probably kill you application by fetching only 1 instance.

MappedSuperclass Alternatives in Grails

In many past projects, I used this JPA / Hibernate approach to add auditing capabilities to a system. It's very effective and unobtrusive.
Is there a Grails #MappedSuperclass alternative (short of coding domain model objects in Java instead of Groovy)? How can one declare a parent class in a table-per-subclass approach without having a table created for it? I've read the GORM documentation (5.2.3 Inheritance in GORM) but besides the table-per-hierarchy vs. table-per-subclass discussion, I did not find any details on how to do this.
Alternatively, what is the recommended way to achieve this type of auditing in Grails?
Essentially, it's as simple as declaring the MappedSuperclass as abstract and Grails will not create a table for it. I realized by re-reading the manual:
GORM supports inheritance both from abstract base classes and concrete persistent GORM entities. I.e. concrete classes are persistent, so abstract ones are not. Pays to read more carefully.
E.g.
abstract class Auditable {
Date dateCreated
Date lastUpdated
}
class Book extends Auditable {
String title
String description
}
Only the book table will be created and it will have the date_created and last_updated columns. Furthermore, as an added bonus, the dateCreated and lastUpdated properties are auto time-stamped by Grails.

Resources