跨两个数据源的Grails GORM域关联

时间:2013-09-12 15:40:13

标签: grails datasource gorm relationship

如果另一个域类使用不同的数据源,是否可以在两个域类(即belongsTo)之间建立关联?这两个数据源也是不同的数据库驱动程序。

我怀疑这可能不可行,但我想在这里与社区联系,看看是否有可能。现在我正在尝试这样做,我得到了通常怀疑的Hibernate错误:

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

样品:

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"
    }
}

3 个答案:

答案 0 :(得分:8)

正如@dmahapatro在他的评论中指出的那样,这与1元素的情况类似,并且创建自己的方法来管理关系是要走的路。这也与我之前关于映射集合的性能问题的讨论有关,所以你可以一石二鸟:http://www.infoq.com/presentations/GORM-Performance

如果您不需要集合,即如果您只使用它来添加子对象的新实例,那么这将起作用,因为get实例的DomainClassB调用将使用它数据源:

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"
    }
}

创建一个新的DomainClassA实例与传统的addTo...方法略有不同,但它并不太糟糕:

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

如果您确实想要访问DomainClassA的所有DomainClassB个实例,可以为此添加方法:

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

但是,由于您自己正在进行查询,因此如果只需要一些实例,则无需加载所有实例,因此您可以执行任何所需的查询。

答案 1 :(得分:0)

我想出了另一个解决方案,如果有人想要一些更“自动化”的东西,如果适用的话,也许它有性能的重复,但如果你像我一样使用MongoDB for Grails插件,它会更容易使用有时候需要使用本机java API来获取文档。

我所做的是在DomainA中,我使用beforeValidate()来分配domainClassBId和onLoad()的值来分配dcB的值。这样,流程对于每个人习惯使用Hibernate都会更自然。保存DomainA时,将DomainB分配给DomainA和onvalidate代码将仅将id保留到相应的数据源。当您加载对象时,例如使用DomainA.find()方法,onLoad代码将确保返回的对象具有DomainB类型的属性而不是Long,然后您可以使用它来查询数据库。它基本上与Burt Beckwith之前表示的方法相同,但在保存和加载DomainA方面更简单。我不确定它是否存在性能问题,我希望有更多经验的人可以帮助我们。

答案 2 :(得分:0)

配置数据库以在两个数据库之间创建DB-Link,然后可以执行以下操作:假设数据库1中的DB Link指向数据库2为database2link,则查询将类似。

从domain_class_A tb内部联接中选择* * tb.domain_class_B_Id = tb2.id上的domain_class_B @ database2link tb2

您可以通过在映射表名称中提供@ database2link来映射DomainClassB,即

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

请注意,我们仅将数据源用作ds1。