Grails GORM Inheritance best practices - grails

I am working on a grails project with potentially 36 domain classes each with a dozen plus unique properties and a handful of shared properties that can be inherited from a base domain class. The problem with this is that grails will generate 1 table with all the properties from all the domain classes that inherit from the base class. This means a table with well over 300 columns which seems problematic on multiple levels. The other route is to do away with inheritance and each domain represents a unique database table. No matter what, either a lot of time will be spent duplicating code or trying to manage the generated database. Is there another option that I am missing?
All thoughts and opinions welcome.

It would appear you are missing the all important tablePerHierarchy mapping value for domain classes. I highly recommend you read the Inheritance Strategies documentation regarding this.
From the documentation:
By default GORM classes use table-per-hierarchy inheritance mapping.
This has the disadvantage that columns cannot have a NOT-NULL
constraint applied to them at the database level. If you would prefer
to use a table-per-subclass inheritance strategy you can do so as
follows:
class Payment {
Integer amount
static mapping = {
tablePerHierarchy false
}
}
class CreditCardPayment extends Payment {
String cardNumber
}
The mapping of the root Payment class specifies that it will not be
using table-per-hierarchy mapping for all child classes.

Don't use inheritance between classes. It is very hard to make refactors in classes with inheritance.
You can use dynamic behavior for common classes through interfaces, or maybe re-think the design in the model classes.

Related

Using traits for horizontal domain class reuse in Grails, a good idea?

So I want to create 3 plugins which include domain classes and a restful service, and who each build on top of each other.
Conceptually, they would "inherit" the base model this way:
Record > Person > User
However I have Read From The Friendly Manual that inheritance may cause some performance issues.
Then it crossed my mind that since Groovy has horizontal reuse capabilities (i.e. traits), I may very well just define everything in the trait and then implement the trait in the domain class.
Composing domain classes is not an option for me because of the renaming of the fields, and well, the loss of the convenience of IDE auto-completion.
My two questions are:
In what part of the Grails project structure would it be best to place these traits.
Can this cause different problems?
The Trait source code should be in
Grails 2: src/groovy/[package][whatever.groovy]
Grails 3: src/main/groovy/[package][whatever.groovy]
For example: src/main/groovy/com/my/package/foo.groovy
The main issue you'll have is that you'll loose the ability to perform polymorphic queries. For example, with inheritance you can do something like this:
def everything = Record.list()
and everything would contain Record, Person, and User instances. Kind of like a SQL union query. When using Traits instead of inheritance you loose this ability.

Adding new relationship to an imported GORM class

Is there a way to add more belongs-to relationships to an imported GORM domain class? Specifically, I'm attempting to use table-per-class to extend a shared subclass, but if I do this in two (or more) locations, and the locations do not have knowledge of each-other then things like:
set.addToParents(parentSet)
Start leading to:
org.hibernate.WrongClassException: Object [id=3482] was not of the specified subclass [com.acumenllc.domaincore.DbSet] : Discriminator: com.acumenllc.tickets.domain.TicketSet
happening everywhere.
A little more background, I'm working on a closure table to keep track of related objects. The base class recognizes the parent-child bi-directional relationship, as well as the ancestor-descendant extension of it. Different applications then extend this class with belongsTo relationships on objects to be represented as nodes in the resultant graph. We specifically want to be able to more-or-less ignore some of these other classes in other applications that happen to share the same database.
Ideally, it would be possible to import our base domain class into a new application and, rather than extending into a subclass, re-define the set of relationships that the base class recognizes in the scope of the application.
The only practical way I can see of doing this is with .hbm.xml files. The GORM approach of including hasMany/belongsTo in the code and JPA's approach using annotations are both fairly inflexible to support this sort of mapping. But if you separate the configuration from the code, you can define the relationships for different applications however you like. Creating a hibernate.cfg.xml file and the hbm.xml files is described here in the docs.

EntityFramework database vs model

I understand the fact that generating a model based on the DataBaseFirst method woill produce a collection of entitites on the ORM that are essentially mapped to the DB tables.
It is my understanding, that if you need properties from other entities or just dropdownlist fields, you can make a ViewModel and use that class as your model.
I have an AppDev course that I just finished and the author wrote something that if I understand it correctly, he is referring to change the ORM entities to fit what your ViewModels would look like, hence, no need for ViewModels. However, if you do this, and regenerate the ORM from the database, those new entities that you placed as "ViewModels" would be gone. If you changed the ORM to update the database, then your database structure in SQL Server would be "undone".
Please inform me if my understanding is correct that I simply need to use a ViewModel in a separate folder to gather specific classes and or properties in a superclass or a single class with the properties that I just need and use that as my model....
Here is the excerpt from the author:
EntityFramework is initially a one to one mapping of classes to tables, but you can create a model that better represents the entities in your application no matter how the data is stored in relational tables.
What I think the author may have been hinting at is the concept of complex models. Let's say, for instance, that in your Database you have a Customer Table and an Address Table. A one to one mapping would create 2 model items, one Customer class and one Address class. Using complex model mapping, you could instead create a single Customer class which contained the columns from both the Customer Table and the Address table. Thus, instead of Customer.Address.Street1 you could refer simply to Customer.Street1. This is only one of many cases where you could represent a conceptual model in code differently than the resulting data in storage. Check out the excellent blog series Inheritance with EF CodeFirst for examples of different mapping strategies, like Table Per Hierarchy (TPH), Table Per Type (TPT), Table Per Concrete Class (TPC). Note that even though these examples are CodeFirst, they still apply to Entity Framework even if the initial models are generated from a Database.
In general, if you use DatabaseFirst and then never modify the resulting entities, you will always have a class in code for each table in the database. However, the power of Enity Framework is that it allows you to more efficiently work with your entities by allowing these hybrid mappings, thus freeing you to think about your code without the extra burden of your classes having to abide by rigid SQL expectations.
Edit
When the Database-First or Model-First entities are generated, they are purposely generated as partial classes. You can create your own partials which extend the classes that are generated from Entity Framework without modifying the existing class files. If the models are re-generated, your partial classes will still be intact. Granted, using partials means that you have the Entity Framework default behaviors as well as your extended behaviors, but this isn't usually a huge issue.
Another option is that you can modify the TT files which Entity Framework uses to generate your models, ensuring that your models are always regenerated in the same state.
Ultimately, the main idea is that just because the default behavior of Entity Framework is to map the database to classes 1:1, there are other options and you are never forced into something that isn't efficient for your project.

What are the pros and cons of writing class methods in grails domain classes?

What are the pros and cons of writing class methods in grails domain classes? I am asking, because I often do not see any grails projects with methods inside the domain classes, only data members. Is there a disadvantage to doing so?
When a domain class (not just in grails, but in object oriented programming in general), this is known as an anemic domain model. Martin Fowler proposes that domain logic gets put into the domain class to create a rich domain model. By doing this, domain classes become smarter and know how to perform operations, rather than having another service class that has to operate on the domain class. The pros of having a rich domain model is that the class encapsulates more of its own behavior, and it is more self contained. On the flip side, it does make the domain class more complex. Though I think the domain class should be more than just a business object.
In grails, I tend to try to use a combination of a rich domain model and using services. It's difficult to make a blanket statement as to when a method should be in a domain class and when it should be in a service. As a general rule though, if an operation is complex and requires multiple collaborators, I'll tend to put it in a service class. If the method seems like it should be behavior on the domain class, I'll put it there.
To give a more concrete example, let's take a Person class.
class Person {
String firstName
String lastName
List<Person> friends
}
In our application a person can speak. Now I can have a TalkService that knows how a person talks. But in this case, I think that talk is a core behavior of the person, so I would add a talk method to Person.
Let's say I also have functionality where I want to find all of the friends of friends of people (2nd degree friends). To me, this is not core behavior of a Person, so I woul delegate this out to a service.
To recap, in general I would add methods to the domain class when it is core behavior of the object (e.g. is it a domain method), otherwise, I would put it in a service.
In a Java project, you must have POJO classes that represents the model.
For example: Person, Invoice, Book, ...
Then there is the service layer, which contains interfaces for users to do some database queries, it takes in parameters your Model, and also return Model, and there is the controller layer which is responsible for redirection and inject your services.
In grails, this is very easy using injection of services into your controller
Now, when do we need to use methods inside the domain classes ? it's when only the model which responsible for what do we need to do, for example, how old is a Person X (it's from the date of birth), how many items exist in a Invoice (from the List), the think is we use that only when we manipulate the data of the current object.
For save method for example, you cannot add it in your model
PersonController :
def personService
def save() {
...
Person person = ...
personService.save(person);
...
}
This is more evolutive

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