I'm facing a issue regarding inheritance in Grails.
I have a domain class Person.grooy:
class Person{
String name
String contactNumber
Address address
}
Now I'm extending Person.groovy for Employee and Customer like:
class Employee extends Person{
String designation
}
class Customer extends Person{
String interest
}
Now I want separate table in my database for Employee and Customer having columns of Person i.e name,contactNumber and associate address key.
How could I achieve this. I searched every where but there is nothing for this aspect.
Is this one approach is not possible in GORM.
Please answer.
Thanks Guys
Finally I managed to get what I want just by placing a grails.persistence.Entity annotation to my child domain classes. I also make my parent i.e. Person.groovy abstract and place in src/groovy.
Now I have database hierarchy as I expected but some scaffold issues in controller still persist that will also sorted out with your help.
You need to disable table-per-hierarchy, which is by default enabled in Grails
class Employee extends Person{
String designation
static mapping = {
tablePerHierarchy false
}
}
table-per-hierarchy Ref
If you put your Person class in src/java or src/groovy it won't be mapped to the db.
Remember to import it into your Employee and Customer classes
import com.yourPackage.Person
class Employee extends Person{
}
It looks like inheritance is not the approach we need to follow here. You should create composition with Person class and it will store the properties of Person class in Employee.
class Employee {
Person person
String designation
static embedded = ['person']
}
Gorm Composition
you can put it inside src/java, but that solution will not be standard, as it really will not be treated as a grails domain example once you get deeper into the application.
For example, if you want to create a controller or a test script on the extended domain as per the previous answer, it will be complicated.
As of grails 2.2.x I believe, grails provides you with mapWith. You can use that for a more maintainable solution
class Employee{
static mapWith = "none"
}
Related
I'd like to use an Enum or String in place of column class to map on table inheritance in Grails.
For exemple
#Entity
#Table(name = "person")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorValue("USR")
#DiscriminatorColumn(length = 3, discriminatorType = DiscriminatorType.STRING, columnDefinition = "CHAR(3) NOT NULL", name = "type")
public class People implements Serializable {
I couldn't find a way to change it into documentation.
Going to try to answer your question but in all honesty unsure where your point is wavering towards since it is left open ended as to to the actual question raised Inheritance and there appears to be no signs of inheritance on example provided.
My first pointer would be here.
This does work or had it working on default grails 3.2.8 but upon updates to latest gorm there was issues with updating existing records. I gave up and did it as separate classes at the time.
If your question relates to having table per class then above setup is what you need for grails.
Typically you would do :
abstract class Something {
static mapping = {
cache true
//tablePerConcreteClass false
tablePerHierarchy false
//discriminator value: 'institution'
}
}
class SomethingElse extends Something {
static mapping={
//discriminator value: 'somethingElse'
}
}
The abstract class definition vs non abstract has different adverse effects into how your tables get created and how your whole model will then work. It all depends on the requirement.
The problem with above is when it comes to querying the class in HQL I faced a problem where when I tried to query instance.class I got a numeric number back from HQL rather than actual domainClass instance and obviously discriminator was first point of reach.
The actual trick in these extended classes is if in HQL something.class does not return actual class name to try
String query = """ select new map(type(s) as className,s.id as id) from Something s """
The type(s) will now return actual string class name. (Maybe where you are stuck)
Usually you can do in HQL:
when s.class = SomethingElse then do something
and HQL will work out the actual className based on that matching domainClass name.
Somehow I don't think this is what you are after though
EDIT: Per my answer below, this seems fixed by a "grails clean". You bang your head in frustration and you overlook the obvious sometimes.
For some time we've had the following structure of domain objects:
abstract class Company {
String name
...
}
and multiple children similar to the following all with different "owner" objects. Each concrete class has it's own table in the DB.
class CompanyChild extends Company {
static belongsTo = [owner:SomeDomain]
...
}
I'm adding another property to the abstract parent for various reasons, so the parent now looks more like the following (CompanyType is an enum):
abstract class Company {
String name
CompanyType companyType
...
}
This all seems pretty straightforward. Now in company service, somewhere I'm doing this:
log.debug("Saving new company type=$companyType")
def company= new Company(name: 'Acme', companyType: companyType, <other properties here>)
log.debug("company object has type=${company.companyType}")
The log shows...
CompanyService Saving new company type=NONPROFIT
CompanyService company object has type=null
What the heck is happening here? It really seems like ${company.companyType} should not be null.
If I add
company.companyType = companyType
after the object is created it works, but there's something I'm failing to understand.
Edit: grails version is 2.3.11
Sometimes you focus so much on a problem that you don't step back and thing... maybe I need to do a full "grails clean"...
Clean and recompile seems to have been my answer.
I am a beginner in GRAILS so i am hoping some help on the issue i am facing.
I have read the documentation but i am still vague on the idea of relationships in grails. In grails, you could have 4 types of relationship between domain classes.
1 to 1
1 to many
many to 1
many to many
Grails has three constructs to define relationships
static hasMany =
static belongsTo =
static hasOne =
My question and dilemma is why do we need these three constructs to define a relation when we could just specify what type of objects each class has that would automatically define relationship between domain classes.
for example
To define many to many i could have two classes designed this way
class Author{
Set<Book> books
}
class Book{
Set<Author> authors
}
For 1 to many and many to 1
class Author{
Set<Book> books
}
class Book{
String title
}
for one to one
class Author{
Book book
}
class Book{
Author author
}
I appreciate it if anyone can give me a clear, easy to understand explanation. Thank you!
Everything you defined there should work fine. You don't have to use any of the other stuff that you mentioned that GORM offers, but there are reasons that you might want to. For example, you can write a class like this:
class Author{
Set<Book> books
}
That is not the same thing as this:
class Author {
static hasMany = [books: Book]
}
When you use hasMany, Grails generates this for you...
class Author {
Set<Book> books
def addToBooks(Book b) {
books.add(b)
this
}
def addToBooks(Map m) {
books.add(new Book(m))
this
}
def removeFromBooks(Book b) {
books.remove(b)
this
}
}
That isn't exactly what is generated, but that is some of the stuff that you might care about.
There is more to it than is represented there. For example, if the Book has a reference back to the Author, the addToBooks methods will hook that back reference up for you.
There are other behaviors associated with the other properties you mentioned. For example, the hasOne property switches the direction in which the foreign key points on the persistence model. The belongsTo property enforces cascading of certain events. etc.
Take a look at the GORM docs at http://grails.org/doc/latest/guide/GORM.html for more information.
We use dynamic scaffolding in our project and hence place maximum coding in Domain itself.
I have a requirement where I want to retrieve a collection for a Domain class property from the same domain class.
Example :
class Person{
String name
String school
}
school property should be a dropdown containing list of all schools so far available in the Person table. If no value available, it can be empty dropdown.
Any suggestions to achieve this in domain class itself?
That is what
static hasMany is for: http://grails.org/doc/latest/ref/Domain%20Classes/hasMany.html
in your case, something like below will work , once you create a School Domain object:
class Person{
...
static hasMany = [schools: School]
...
Given these functional requirements:
User Management
Administrator
Librarian
Borrower
*The users have the option of logging-in via OpenID.
Property Management
Book
Memorandum
Circular
License
Normally, I would implement these in Java as:
interface User {}
class Librarian implements User {}
class Administrator implements User {}
class Borrower implements User {}
class OpenID {} //all Users HAS AN OpenID attribute (NULL if non-openId login)
interface Property{}
class Book implements Property{}
class Memorandum implements Property{}
class Circular implements Property{}
class License implements Property{}
But our project will use Groovy & Grails, which I haven't experience using yet. My question is,
how should the domain classes be designed based on the requirements above? I can't use an interface, and it seems inheritance is not a good practice. My idea is to use composition, though I'm quite bothered by the database tables that would be generated. What are the best practices in this situation?
Well first of all lets correct it, you can use inheritance in this case. You just need to change the convention of has a relationship to is a relationship.
Few factors to keep note of:
1. Grails works on convention over configuration.
2. You can use GORM which wraps the persistence layer and creates an Object Mapping for the underlying persistence layer with the help of Hibernate.
As per your functional requirement:-
If you do not want to have the User as part of persistence you can have an abstract class User which can hold the common properties of the User including the openId attribute. It has to be placed in src\groovy directory as per convention (since the base class is abstract, dependency injection will be defied)
The same goes for Property. Abstract Property class in src\groovy.
Now coming to the business models, extend each of the concrete entities (domain classes) from the abstract parent.
Summary:-
Create grails app
Under src\groovy(for example, I am considering a basic structure):
User.groovy:-
abstract class User{
String name
String emailId
OpenID openId
}
Property.groovy:-
abstract class Property{
String propertyName
}
Under grails-app/domain:
Librariran.groovy:-
class Librarian extends User{
//Attributes specific to Librariran
static constraints = {
}
static mapping = {
}
}
Book.groovy:-
class Book extends Property{
//Attributes specific to Book
static constraints = {
}
static mapping = {
}
}
So on and so forth. Groovy objects under grails-app/domain are considered concrete entities by Grails convention. More information you can obviously find here. You can also use composition if you come across scenarios, in fact I already mentioned that in User having OpenId.
Note:- This is context to latest version of Grails (> 2.x)