Grails GOLD Domain Association for Two Data Sources

Is it possible to have a relationship between two domain classes (i.e. belongsTo ) if another domain class uses a different data source? Two data sources are different database drivers.

I suspect this may not be possible, but I wanted to contact the community here to find out if this is possible. Now I'm trying to do this, and I get the usual suspicious Hibernate error:

Invocation of init method failed; nested exception is org.hibernate.MappingException: An association from the table domain_class_A refers to an unmapped class: DomainClassB

Example:

 class DomainClassA { static belongsTo = [dcB: DomainClassB] static mapping = { datasource "ds1" table name: "domain_class_A", schema: "schema_A" } } class DomainClassB { static hasMany = [dcA: DomainClassA] static mapping = { datasource "ds2" table name: "domain_class_B", schema: "schema_B" } } 
+9
grails gorm datasource relationship
source share
3 answers

As @dmahapatro points out in his comment, this is like a 1-element case, and creating your own relationship management methods is the way to go. This is also related to a conversation I made some time ago about performance issues with matching collections, so you can kill two birds with one stone: http://www.infoq.com/presentations/GORM-Performance

If you do not need a collection, i.e. if you use it only to add new instances of the child, this will work because the get call on the DomainClassB instance will use its data source:

 class DomainClassA { Long domainClassBId private DomainClassB dcB DomainClassB getDomainClassB() { if (!dcB && domainClassBId) { dcB = DomainClassB.get(domainClassBId) } dcB } void setDomainClassB(DomainClassB dc) { domainClassBId = dc.id } static transients = ['domainClassB'] static mapping = { datasource "ds1" table name: "domain_class_A", schema: "schema_A" } } class DomainClassB { static mapping = { datasource "ds2" table name: "domain_class_B", schema: "schema_B" } } 

Creating a new instance of DomainClassA is slightly different from the traditional addTo... approach, but it's not so bad:

 DomainClassB dcb = ... def dca = new DomainClassA(domainClassBId: dcb.id) dca.save() 

If you want to access all instances of DomainClassA for DomainClassB , you can add a method for this:

 Set getDomainClassAs() { DomainClassA.findAllByDomainClassBId(id) } 

But since you make the request yourself, you do not need to download all instances if you only need some, so you can make any requests that you want.

+8
source share

I came up with another solution, if someone wants something more "automated", if applicable, it may have performance implications, but it makes it easier to work with it specially if you, like me, use MongoDB for the Grails plugin, which sometimes makes it necessary to use the native Java API to retrieve documents.

What I did is that in DomainA I use beforeValidate () to assign the value of domainClassBId and onLoad () to assign the value of dcB. Thus, the flow will be more natural for what everyone is used to with Hibernate. When saving DomainA, a will pointing DomainB to DomainA and the onvalidate code will only save the identifier of the corresponding data source. When you load objects, for example, using the DomainA.find () method, the onLoad code will ensure that the returned object has a property of type DomainB instead of Long, which is then used to query the database. This is basically the same approach that Burt Beckwith previously outlined, but in a simpler way in terms of saving and loading DomainA. Again, I'm not sure that he has a performance problem, something that I would like someone with more experience could help us with.

0
source share

Configure your database to create DB-Link between the two databases, then you can do something like the following: Let's say DB Link in database 1 pointing to database 2 is database2link, then your query will look like this.

select * from domain_class_A internal connection tb domain_class_B @ database2link tb2 on tb.domain_class_B_Id = tb2.id

And you can map DomainClassB by specifying @ database2link in the table name in the mapping, i.e.

static mapping = {data source "ds1" table name: "domain_class_B @ database2link", schema: "schema_B"}

Please note that we use the data source only as ds1.

0
source share

All Articles