2011-03-31 171 views
5

我有三個領域類:啤酒,評論和審稿人。如何使用GORM創建組合主鍵?

我想讓Review表在Beer和Reviewer之間創建多對多的關係,所以我希望Review的主鍵是來自Beer和Reviewer的id字段的組合。我遵循這個Grails文檔。

http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.5.2.5%20Composite%20Primary%20Keys

這裏是我的領域類。

class Beer { 
    String name 
    String type 
    Brewery breweryId 

    static hasMany = [ reviews : Review ] 

    static constraints = { 
    } 
} 

class Reviewer { 
    String screenName 

    static hasMany = [ reviews : Review ] 

    static constraints = { 
    } 
} 

class Review implements Serializable { 
    int score 
    Beer beer 
    Reviewer reviewer 


    static constraints = { 
    } 

    static mapping = { 
     id composite:['beer', 'reviewer'] 
    } 
} 

我得到編譯錯誤,但這裏對計算器另一個答案說我需要添加implements Serializable。這照顧了錯誤,但是當我查看數據庫時,我仍然沒有得到一個組合主鍵。

這是我看到表格定義時所看到的。我正在使用Postgres。

 Table "public.review" 
    Column | Type | Modifiers 
-------------+---------+----------- 
id   | bigint | not null 
version  | bigint | not null 
beer_id  | bigint | not null 
reviewer_id | bigint | not null 
score  | integer | not null 
Indexes: 
    "review_pkey" PRIMARY KEY, btree (id) 
Foreign-key constraints: 
    "fkc84ef75823f39326" FOREIGN KEY (beer_id) REFERENCES beer(id) 
    "fkc84ef7587c483106" FOREIGN KEY (reviewer_id) REFERENCES reviewer(id) 

我會很高興只有一個具有唯一約束的複合索引,但我無法弄清楚如何做到這一點。我已經能夠創建一個非唯一的組合索引,但是這有兩個問題。一,它是非獨特的。二,列在索引中按字母順序指定(beer_id,reviewer_id)。我想指定索引中列的順序。

回答

0

試試這個,在您的域名審查域類:

static constraints = { 
    review(unique: ['beer','reviewer']) 
} 

您可能需要刪除該表,並讓格姆重建。

上述限制意味着評論必須包含啤酒/評論者組合的唯一記錄。對於評論者有多種啤酒,反之亦然,但評論是獨一無二的。

2

我已經實現了類似的情況,有一些不同的條件:

  1. 有沒有hasMany關係。
  2. 查詢到加盟類由HQL
  3. 做使用更詳細的填

在實施這樣的,mysql數據庫就可以了。 (beer_id,reviewer_id)是主鍵。

class Review implements Serializable { 

    Beer beer 
    Reviewer reviewer 

    static Review get(long beerId, long reviewerId) { 
     find 'from Review where beer.id=:beerId and reviewer.id=:reviewerId', 
      [beerId: beerId, reviewerId: reviewerId] 
    } 

    static boolean remove(Beer beer, Reviewer reviewer, boolean flush = false) { 
     Review instance = Review.findByBeerAndReviewer(beer, reviewer) 
     instance ? instance.delete(flush: flush) : false 
    } 
    ... 

    static mapping = { 
     table "REVIEW" 
     id composite: ['beer', 'reviewer'] 
     beer(column: "beer_ID") 
     reviewer(column: "reviewer_ID") 
     version false 
    } 
} 

我不知道究竟是什麼原因導致了您的問題,但希望這給您一些關於問題可能出現的提示。

2

我接受了Grails的授權,我不應該使用複合主鍵作爲明智的建議,而是避免它。如果是這樣,我相信解決您的問題的一個可行的替代方案是複合唯一約束。 REF:http://grails.org/doc/1.1.x/ref/Constraints/unique.html

Jacco的答案似乎是不正確的,雖然看起來視覺上非常接近正確,這裏是你如何寫一個複合唯一約束這個問題:

static constraints = { 
    beer(unique: 'reviewer') 
} 

而如果程序員想連桿3個數據庫字段作爲唯一的,正確的形成是:

static constraints = { 
    beer(unique: ['anotherField','reviewer']) 
} 

看起來像 Jacco的答案,但類名不作爲約束的第一個字符串,使用第一個字段名稱。

我只是用這個代碼結構在我自己的項目應用程序,它似乎是正確的行爲,又見這對單位如何測試唯一約束: http://www.ibm.com/developerworks/java/library/j-grails10209/index.html (參見清單11)