Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails GORM domain association across two datasources

Is it possible to have an association between two domain classes (i.e. belongsTo) if the other domain class uses a different datasource? The two datasources are different database drivers too.

I suspect this may not be possible, but I wanted to reach out to the community here to see if it was possible. Right now I'm trying to do it and I am getting the usual suspected 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

Sample:

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"
    }
}
like image 840
Thomas Farvour Avatar asked Sep 12 '13 15:09

Thomas Farvour


1 Answers

As @dmahapatro points out in his comment, this is similar to the 1-element case, and creating your own methods to manage the relationship is the way to go. This is also related to a talk I did a while back about performance issues with mapped collections, so you can kill two birds with one stone: http://www.infoq.com/presentations/GORM-Performance

If you don't need the collection, i.e. if you only use it to add new instances of the child object, then this will work because the get call for the DomainClassB instance will use its datasource:

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 DomainClassA instance is a bit different from the traditional addTo... approach, but it's not too bad:

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

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

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

But since you're doing the query yourself, you don't have to load all of the instances if you only need some, so you can do whatever queries you want.

like image 106
Burt Beckwith Avatar answered Nov 16 '22 00:11

Burt Beckwith