Inheritance in Grails
In Grails, we can have inheritance with the abstract base class as well as persistent base class. Lets take an example to explain this.(All the classes are in the package com.intelligrape.example)
[java]
class Blog{
String authorName
static constraints = {
authorName (nullable:false)
}
}
class TextBlog extends Blog{
String textContent
static constraints = {
textContent (nullable:false)
}
}
class PodCast extends Blog{
byte[] content
static constraints = {
content (nullable:false)
}
}
[/java]
By creating such class structure Grails will create a single table and all the three classes will share it. Our table will look like as follow
[java]
+————–+————–+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+————–+————–+——+—–+———+—————-+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| version | bigint(20) | NO | | NULL | |
| author_name | varchar(255) | NO | | NULL | |
| class | varchar(255) | NO | | NULL | |
| text_content | varchar(255) | YES | | NULL | |
| content | tinyblob | YES | | NULL | |
+————–+————–+——+—–+———+—————-+
[/java]
We can see that other than the declared fields Grails created three more fields
id : Auto increment field, used as an identifier and managed by Grails itself
version : Used for optimistic locking, increments each time when object is updated
class : Discriminator column used to identify what specific type of blog is associated with given row e.g; com.intelligrape.example.TextBlog
There is a drawback with this approach, as you can see in the table, column text_content and content fields are nullable true although we have defined them as nullable false in domain class. Consequence of storing all kind of blog data in single table is that we can’t have non nullable columns in sub classes but because of single table, joins are not fired and our queries will be faster. Second disadvantage could be the long discriminator, which makes it difficult to read the data of a particular class in sql.
If you dont like having single table for all the data, Grails give you freedom to create multiple tables for each class. You just need to add the following mapping block in base class
[java]
static mapping = {
tablePerHierarchy false
}
[/java]
Now you can see three different tables for each class. But the major drawback in this approach is whenever you save the instance of sub-class it executes two queries for save like following
[java]
Hibernate: insert into blog (version, author_name) values (?, ?)
Hibernate: insert into text_blog (text_content, id) values (?, ?)
[/java]
Second drawback is again on query performance. Whenever you execute some GORM query for fetching data it executes join query e.g; TextBlog.list() method will have the following join query
[java]
Hibernate: select this_.id as id2_0_, this_1_.version as version2_0_, this_1_.author_name as author3_2_0_, this_.text_content as text2_4_0_ from text_blog this_ inner join blog this_1_ on this_.id=this_1_.id
[/java]
Now its our decision which makes more sense to our application.
Hope it helps