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
}
}
Related
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'
}
}
}
}
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"
I need to map Domain classes and subclasses of a legacy database.
The model thath I need to recreate with Grails is to this tables:
Tables structure
CARD_PAYMET and CHEQUE_PAYMENT is subclasses of PAYMENT and share a composite key of two field: OrderId and PaymentId.
I try some ex scenarios, but I can´t arrive to solution. None of then recreate the same model data, and I can´t change this model.
Can any one help me?
Thanks.
Your database looks like a good fit for table-per-subclass inheritance. First, since you're using a composite primary key, your domain classes need to implement the Serializable interface. Then it's a matter of mapping each table column to a property.
import groovy.transform.EqualsAndHashCode
#EqualsAndHashCode(includes=['orderId', 'paymentId'])
class Payment implements Serializable {
int orderId
int paymentId
float amount
static mapping = {
version false
tablePerHierarchy false
id composite: ['orderId', 'paymentId']
orderId column: 'OrderId'
paymentId column: 'PaymentId'
/* Assuming case-insensitive db, so I left out 'Amount'. */
}
}
class CardPayment extends Payment {
String cardType
static mapping = {
version false
cardType column: 'CardType'
}
}
class ChequePayment extends Payment {
int checkNumber
static mapping = {
version false
checkNumber column: 'CheckNumber'
}
}
Note: In this example I used Groovy's EqualsAndHashCode AST transformation to implement Serializable.
With the domain classes in place you'll be able to do GORM polymorphic queries:
def payments = Payment.list() // All Payments (Payment, CardPayment, and ChequePayment).
def cardPayments = CardPayment.list() // Only CardPayments.
...
def nicePayments = Payment.where { amount > 1000 }.list()
I see there is a strategy for a one to one mapping for domain objects across different databases. But I am trying to associate two Domain objects that are in different datasources and have a one to many relationship.
class DomainA {
// default data source
}
class DomainB {
static hasmany = [domainA: DomainA]
static mapping = {
datasource 'ds2'
}
}
Any suggestions on how to make this work? Or a workaround?
Found a solution to this and it works pretty well. Solution is to create a join table in the schema you own.
E.g.
class DomainA {
// default data source
}
class DomainB {
List<DomainA> domainAList
static transients = ['domainAList']
static hasmany = [domainAIds: Integer]
static mapping = {
datasource 'ds2'
domainAIds joinTable: [name: 'DOMAINB_DOMAINA', key: 'DOMAINB_ID', column: 'DOMAINA_ID']
}
List<DomainA> getDomainAList(){
domainAList = domainAIds.collect { DomainA.get(it) }
domainAList
}
}
I have a tRNA class which may or may not have an associated grRNA, but will be associated to cRNA.
So I can have this relationship :
tRNA -> grRNA -> cRNA
Or this relationship (in this case we don't have grRNA data) :
tRNA -> cRNA
What is the best way to implement this relationship (we may not have grRNA sometimes) via Grails/Gorm ?
Best domain class design ?
You could have grRNA and cRNA be subclasses of a parent, with tRNA having an association with the parent, and grRN associating with cRNA.
In your database tables you would need a class column to define the class (discriminator in the GORM object).
Edit:
Something like:
class GenericRna {
//Properties
//Assuming this is mapped to a database table as well, you'd need:
static mapping = {
table 'generic_rna'
discriminator column: 'class'
}
}
class CRna extends GenericRna {
//Properties
discriminator value: 'CRna'
}
class GrRna extends GenericRna {
//Properties
static hasMany = [cRnas: CRna]
discriminator value: 'GrRna'
}
class TRna {
static hasMany = [genericRnas: GenericRna]
}
Technically I believe that if you use 'class' as your discriminator column name, and the class names as the values, you do not need the 'discriminator' lines.