Abstract domain class and tablePerHierarchy - grails

In my Grails 3.2.6 app I have 2 classes:
abstract class Base {
static mapping = {
tablePerHierarchy false
}
}
and
class Child extends Base {
static mapping = {
collection 'child'
}
}
Upon saving the instances of Child are dumped into "base" collection (with _class = Child field) instead of "child".
How to make it work right?
UPDATE
I defined the Base as a trait under src/main/groovy:
trait Base { }
and
class Child implements Base { }
then it worked properly.

In your Child class mapping method, add this
table "child"

Related

Grails 3 domain class composition

With Grails 3.2.5, hibernate 5.1.2 core.
I have a legacy database that has several clobs in a table. In order to avoid eager fetching, in earlier versions of Grails I defined a domain class that contained only those clobs in order to make them accessed via an (apparent) association which could then be lazily fetched. A sketch of the setup:
class Comment {
String someField // eager
CommentText cmntText // lazy
static mapping = {
id column: 'COMMENT_ID', generator:'sequence', params:[sequence:'cmnt_seq']
}
In a separate domain class file:
class CommentText {
String userComment
static mapping = {
table 'COMMENT'
id generator:'assigned'
userComment sqlType:'clob'
}
As noted, clob column 'user_comment' exists in the single table 'COMMENT'.
In 3.2.5, when doing this I get an error that column 'comment_text_id' is not defined in table 'comment'. This didn't use to be the case, nor should the field have to exist.
On a similar note, in another case I define a composite domain class (a class defined in the same file as the actual domain class). In this case too I get an error about a missing id:
class A {
B b
}
class B {
String someField
}
In this case I get an error saying that field b_id is not in table 'A'. But - it's supposed to be embedded composition, it should not be there.
I'm building within Intellij if that is relevant.
With GORM 6.1 this is now possible with a single domain class
import grails.gorm.hibernate.annotation.ManagedEntity
import static grails.gorm.hibernate.mapping.MappingBuilder.*
#ManagedEntity
class Comment {
String someField
String userComment
static constraints = {
}
static final mapping = orm {
id {
generator("sequence")
params(sequence:'cmnt_seq')
}
userComment = property {
lazy(true)
column {
sqlType 'clob'
}
}
}
}

Where adding pessimistic lock in using hasMany?

Suppose I have this code
Domain
class Parent{
static hasMany = [Childs:Child]
}
class Child {
String name
}
Controller
def ParentInstance = Parent.get(1) //Parent.lock(1)
ParentInstance.Childs.each {
//it.lock()
it.name = "titi"
}
ParentInstance.save()
The lock should be added for each child instance or just adding it when getting the parent?

Grails - Validation of embedded object attributes only while updating

I have a grails domain class with an embedded object, I want to validate the embedded object's attributes only while updating.
I know I can do this on a normal grails domain class by using a custom validator and checking if the domain's class id is not null.
I can't do this because of the lack of an id on an embedded object.
There is a little example of what I want to do.
//This is on domain/somePackage/A.groovy
class A{
B embeddedObject
static embedded = ['embeddedObject']
static constraints = {
embeddedObject.attribute validator:{val, obj-> //The app fails to start when this code is added!!
if(obj.id && !val) //if the id is not null it means the object it's updating...
return 'some.error.code'
}
}
}
//this class is on src/groovy/somePackage/B.groovy
class B{
String attribute
static constraints={
attribute validator:{val,obj->
if(obj.id && !val) //This will fail too! because the lack of an id on this object....
return 'some.error.code'
}
}
}
Is there a way to get the id of the 'parent' on the embedded object??
Any help will be appreciated
way too complicated:
class A{
B embeddedObject
static embedded = ['embeddedObject']
static constraints = {
embeddedObject validator:{ val, obj ->
if( obj.id && !val.attribute )
return 'some.error.code'
}
}
}

How to inherit GORM mapping from non domain class?

Permanently I have some tables and some hibernate classes with mapping annotations. And this classes have abstract superclass with mapping annotations also. But in this superclass there is no table association mapping. All tables are identified in the subclasses.
I'm trying to migrate this mapping to GORM model. But all strategies: TablePerHierarchy and TablePerSubclass not approach for my case because all tables is created and can't be changed.
I created superclass in the 'src/groovy/somepackage/' and want to inherit mapping and constraints from this class to my subclasses in the 'domain' folder. For constraints it works good but for mapping I can't find documentation how to do this.
Does anyone have any ideas?
Example.
In the non-domain folder:
absract class A {
String a
static mapping = {
a column: "column_A"
}
}
In the domain folder:
class B extends A {
String b
static mapping = {
b column: "column_B"
}
}
And
class C extends A {
String c
static mapping = {
c column: "column_C"
}
}
Needs to get two tables with the column 'column_A' in each of them.
It's possible using the clone and delegate features. Here's what I did:
class B extends A {
static mapping = {
def copyMapping = A.mapping.clone()
copyMapping.delegate = delegate
copyMapping.call()
}
}
This can now be done a bit more straight forwardly:
class B extends A {
static mapping = {
includes A.mapping
}
}

How can a Domain Class cascade 'all-delete-orphan' to a child it has no reference to?

In Grails you can have a child class:
class Child {
Father father
static belongsTo = [Father, Mother]
}
With two parent classes
class Mother{
}
class Father {
}
It appears that if I father.delete(), then Grails throws a database error saying that the Father can't be deleted because the child is still around.
How do I cascade all-delete-orphan the Child if the Father class doesn't have a direct reference to the Child class?
Make it bi-directional using hasMany.
class Mother{
static hasMany = Child
}
class Father{
static hasMany = Child
}
Doing this should make the cascading work such that when you delete one of the parents the child will also be deleted.
Peter Ledbrook has a good article that covered this
GORM Gotchas Part 2
I couldn't get the belongsTo only part to work, but this works for me:
class Father {
static hasMany = [children: Child]
}
class Child {
static belongsTo = [father: Father]
}
void testDeleteItg() {
def father = new Father().save()
def child = new Child()
father.addToChildren child
child.save()
def childId = child.id
father.delete(flush:true)
assertNull(Child.get(childId))
}

Resources