5

Beer、Review、および Reviewer の 3 つのドメイン クラスがあります。

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

コンパイル エラーが発生していましたが、stackoverflow に関する別の回答では、追加する必要があるとのことでした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)

一意の制約を持つ複合インデックスだけで満足しますが、その方法もわかりません。一意ではない複合インデックスを作成できましたが、これには 2 つの問題があります。1つ、それはユニークではありません。2 つ目は、列がインデックス (beer_id、reviewer_id) でアルファベット順に指定されていることです。インデックス内の列の順序を指定したいと思います。

4

3 に答える 3

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

問題の正確な原因はわかりませんが、これが問題の原因についてのヒントになることを願っています。

于 2011-04-01T03:06:49.573 に答える
2

私は、複合主キーを使用すべきではないという Grails の命令を賢明なアドバイスとして受け取り、それを避けています。もしそうなら、私はあなたの問題を解決するための実行可能な代替手段が複合一意制約であると信じています。参照: http://grails.org/doc/1.1.x/ref/Constraints/unique.html

Jaccoの答えは正しくないようですが、視覚的には非常に正しいように見えますが、この問題に対して複合一意制約を記述する方法は次のとおりです。

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

一方、プログラマーが 3 つの db フィールドを一意にリンクしたい場合、正しい形式は次のとおりです。

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

Jaccoの答えのように見えますが、クラス名は制約の最初の文字列として使用されず、最初のフィールド名が使用されます。

私は自分のプロジェクトアプリでこのコード構造を使用しましたが、正しく動作しているようです。一意の制約を単体テストする方法については、こちらも参照してください: http://www.ibm.com/developerworks/java/library/j -grails10209/index.html (リスト 11 を参照)

于 2011-09-12T03:47:19.060 に答える
0

これを試してください。ドメインでドメインクラスを確認してください。

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

テーブルを削除して、Gormに再作成させる必要がある場合があります。

上記の制約は、レビューがビールとレビューアの組み合わせの一意のレコードで構成されている必要があることを意味します。レビュー担当者が複数のビールを持っている場合やその逆の場合は、まだ多対多ですが、レビューはユニークです。

于 2011-03-31T18:56:23.143 に答える