Grails 与 joinTable 的一对多映射

发布于 2024-10-11 21:09:13 字数 1466 浏览 9 评论 0原文

我有两个域类。一个是“合作伙伴”,另一个是“客户”。客户可以是合作伙伴的一部分,并且合作伙伴可以有 1 个或多个客户:

class Customer {
    Integer id
    String name
    static hasOne = [partner:Partner]
    static mapping = {
        partner joinTable:[name:'PartnerMap',column:'partner_id',key:'customer_id']
    }
}

class Partner {
    Integer id
    static hasMany = [customers:Customer]
    static mapping = {
        customers joinTable:[name:'PartnerMap',column:'customer_id',key:'partner_id']
    }
}

但是,每当我尝试查看客户是否是合作伙伴的一部分时,如下所示:

def customers = Customer.list()
customers.each {
     if (it.partner) {
          println "Partner!"
     }
}

我收到以下错误:

org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select this_.customer_id as customer1_162_0_, this_.company as company162_0_, this_.display_name as display3_162_0_, this_.parent_customer_id as parent4_162_0_, this_.partner_id as partner5_162_0_, this_.server_id as server6_162_0_, this_.status as status162_0_, this_.vertical_market as vertical8_162_0_ from Customer this_]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query

它看起来好像 Grails认为partner_id是Customer查询的一部分,其实不是...它在PartnerMap表中,应该找到customer_id,然后从相应的partner_id中获取Partner。

有人知道我做错了什么吗?

编辑:我忘了提及我正在使用旧数据库表执行此操作。所以我有一个 Partner、Customer 和 PartnerMap 表。 PartnerMap 只有一个 customer_id 和 Partner_id 字段。

I have two domain-classes. One is a "Partner" the other is a "Customer". A customer can be a part of a Partner and a Partner can have 1 or more Customers:

class Customer {
    Integer id
    String name
    static hasOne = [partner:Partner]
    static mapping = {
        partner joinTable:[name:'PartnerMap',column:'partner_id',key:'customer_id']
    }
}

class Partner {
    Integer id
    static hasMany = [customers:Customer]
    static mapping = {
        customers joinTable:[name:'PartnerMap',column:'customer_id',key:'partner_id']
    }
}

However, whenever I try to see if a customer is a part of a partner, like this:

def customers = Customer.list()
customers.each {
     if (it.partner) {
          println "Partner!"
     }
}

I get the following error:

org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select this_.customer_id as customer1_162_0_, this_.company as company162_0_, this_.display_name as display3_162_0_, this_.parent_customer_id as parent4_162_0_, this_.partner_id as partner5_162_0_, this_.server_id as server6_162_0_, this_.status as status162_0_, this_.vertical_market as vertical8_162_0_ from Customer this_]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query

It looks as if Grails is thinking partner_id is a part of the Customer query, and it's not... It is in the PartnerMap table, which is supposed to find the customer_id, then get the Partner from the corresponding partner_id.

Anyone have any clue what I'm doing wrong?

Edit: I forgot to mention I'm doing this with legacy database tables. So I have a Partner, Customer and PartnerMap table. PartnerMap has simply a customer_id and partner_id field.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鲜血染红嫁衣 2024-10-18 21:09:13

鉴于当您需要连接表时 1-many 的工作方式,我认为标准 GORM 不可能使其双向并访问客户的合作伙伴。但是您可以使用域类映射联接表并以这种方式访问​​内容:

Customer:

class Customer {
   String name
   def getPartner() {
      PartnerMap.findByCustomer(this)?.partner
   }
}

Partner:

class Partner {
   String name
   def getCustomers() {
      PartnerMap.findAllByPartner(this)*.customer
   }
}

PartnerMap:

import org.apache.commons.lang.builder.HashCodeBuilder

class PartnerMap implements Serializable {

   Partner partner
   Customer customer

   boolean equals(other) {
      if (!(other instanceof PartnerMap)) {
         return false
      }

      other.partner?.id == partner?.id &&
         other.customer?.id == customer?.id
   }

   int hashCode() {
      def builder = new HashCodeBuilder()
      if (partner) builder.append(partner.id)
      if (customer) builder.append(customer.id)
      builder.toHashCode()
   }

   static PartnerMap get(long partnerId, long customerId) {
      find 'from PartnerMap where partner.id=:partnerId and customer.id=:customerId',
         [partnerId: partnerId, customerId: customerId]
   }

   static PartnerMap create(Partner partner, Customer customer, boolean flush = false) {
      new PartnerMap(partner: partner, customer: customer).save(flush: flush, insert: true)
   }

   static boolean remove(Partner partner, Customer customer, boolean flush = false) {
      PartnerMap instance = PartnerMap.findByPartnerAndCustomer(partner, customer)
      instance ? instance.delete(flush: flush) : false
   }

   static void removeAll(Partner partner) {
      executeUpdate 'DELETE FROM PartnerMap WHERE partner=:partner', [partner: partner]
   }

   static void removeAll(Customer customer) {
      executeUpdate 'DELETE FROM PartnerMap WHERE customer=:customer', [customer: customer]
   }

   static mapping = {
      id composite: ['customer', 'partner']
      version false
      table 'PartnerMap'
   }
}

由于您没有使用 hasMany,因此您会丢失 addToXXX 动态方法,但您可以调用 PartnerMap.create() 关联两个实例。您还会丢失域类中的集合和反向引用,但我为它们添加了实用方法。

Given the way 1-many works when you want a join table, I think it's not possible with standard GORM to make it bidirectional and access a Customer's Partner. But you can map the join table with a domain class and access things that way:

Customer:

class Customer {
   String name
   def getPartner() {
      PartnerMap.findByCustomer(this)?.partner
   }
}

Partner:

class Partner {
   String name
   def getCustomers() {
      PartnerMap.findAllByPartner(this)*.customer
   }
}

PartnerMap:

import org.apache.commons.lang.builder.HashCodeBuilder

class PartnerMap implements Serializable {

   Partner partner
   Customer customer

   boolean equals(other) {
      if (!(other instanceof PartnerMap)) {
         return false
      }

      other.partner?.id == partner?.id &&
         other.customer?.id == customer?.id
   }

   int hashCode() {
      def builder = new HashCodeBuilder()
      if (partner) builder.append(partner.id)
      if (customer) builder.append(customer.id)
      builder.toHashCode()
   }

   static PartnerMap get(long partnerId, long customerId) {
      find 'from PartnerMap where partner.id=:partnerId and customer.id=:customerId',
         [partnerId: partnerId, customerId: customerId]
   }

   static PartnerMap create(Partner partner, Customer customer, boolean flush = false) {
      new PartnerMap(partner: partner, customer: customer).save(flush: flush, insert: true)
   }

   static boolean remove(Partner partner, Customer customer, boolean flush = false) {
      PartnerMap instance = PartnerMap.findByPartnerAndCustomer(partner, customer)
      instance ? instance.delete(flush: flush) : false
   }

   static void removeAll(Partner partner) {
      executeUpdate 'DELETE FROM PartnerMap WHERE partner=:partner', [partner: partner]
   }

   static void removeAll(Customer customer) {
      executeUpdate 'DELETE FROM PartnerMap WHERE customer=:customer', [customer: customer]
   }

   static mapping = {
      id composite: ['customer', 'partner']
      version false
      table 'PartnerMap'
   }
}

Since you're not using hasMany, you lose the addToXXX dynamic method, but you can call PartnerMap.create() to relate two instances. You also lose the collection and back-ref in the domain classes, but I added utility methods for those.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文