2011-01-12 15 views
1

Ich habe zwei Domain-Klassen. Einer ist ein "Partner", der andere ist ein "Kunde". Ein Kunde kann ein Teil eines Partners sein und ein Partner 1 oder mehr Kunden hat:Grails Eins-zu-viele-Mapping mit JoinTable

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'] 
    } 
} 

Jedes Mal, wenn ich versuche, zu sehen, ob ein Kunde ein Teil eines Partners ist, wie folgt aus:

bekomme ich folgende Fehlermeldung:

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 

es sieht aus, als ob Grails denkt partner_id ein Teil der Kundenabfrage ist, und es ist nicht ... es ist in der PartnerMap Tabelle, die angeblich finden die customer_id, t Holen Sie den Partner von der entsprechenden Partner-ID.

Wer hat eine Ahnung, was ich falsch mache?

Edit: Ich habe vergessen zu erwähnen, ich mache das mit Legacy-Datenbanktabellen. Also habe ich eine Partner-, Kunden- und PartnerMap-Tabelle. PartnerMap hat einfach ein customer_id- und partner_id-Feld.

Antwort

5

Angesichts der Art und Weise, wie 1-many arbeitet, wenn Sie eine Join-Tabelle wollen, ist es meiner Meinung nach mit Gorm nicht möglich, es bidirektional zu machen und auf den Partner eines Kunden zuzugreifen. Aber man kann die Tabelle beitreten Karte mit einem Domain-Klasse und den Zugang Dinge, die Art und Weise:

Kunde:

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

Da Sie Wenn Sie hasMany nicht verwenden, verlieren Sie die dynamische Methode addToXXX, aber Sie können PartnerMap.create() aufrufen, um zwei zu verknüpfen Instanzen. Sie verlieren auch die Auflistung und Zurück-Ref in den Domänenklassen, aber ich habe Hilfsmethoden für diese hinzugefügt.

+0

Hoppla, ich habe vergessen zu erwähnen, ich mache das mit altem Datenbankkram ... Also muss ich mit vordefinierten Tabellen arbeiten. Ich habe eine Kunden-, Partner- und PartnerMap-Tabelle. PartnerMap ist einfach ein Feld customer_id und partner_id. Beschränkt das mich? – intargc

+0

Ich habe gerade festgestellt, dass dieses Problem nur besteht, wenn man versucht, dieses Zeug in die Grails-Konsole zu laden. Ich habe keine Ahnung, warum ... Ich nahm an, dass die Grails-Konsole die Umgebung ähnlich wie Rails auflädt ... – intargc

+0

Ich habe den Code überarbeitet, aber wenn es außerhalb der Konsole funktioniert, sollte die einfachere Lösung verwendet werden. Die Konsole ist der Grails-Laufzeitumgebung sehr ähnlich, aber in der Run-App oder bei der Bereitstellung in einem Krieg ist viel los, und die Konsole nähert sich nur dieser Umgebung an. –