5

私は、比較的単純なGrailsプロジェクトでカスケード削除動作を生成するための適切な構成を生成するのに苦労してきました。

次の単純なドメインクラスがあるとします。

class Author {
    String name
    static constraints = {
    }
}

class Book {
    String title
    Author author
    static constraints = {
    }
}

著者を作成してから、その著者が書いた本を作成した場合、最初に手動で本を削除しないと、著者を削除できません。「整合性制約違反」が発生します。MySQL(基礎となるデータベース)がGrailsによって作成され、「book」テーブルの「author」列に「Restrict」として「外部キー制約」があるため、これは驚くべきことではありません(この動作は、Grailsからの期待と一致しています。私が理解しているドキュメント)。

ここで、ブックテーブルの「author」列の基になるデータベース制約を「Restrict」から「Cascade」に手動で変更すると、希望する動作が得られます。つまり、著者を削除すると、すべての本も削除されます。

ですから、私がやりたいのは、著者列に「ondeletecascade」を含む「book」テーブルを作成する方法でGrailsの「Book」クラスを変更することです。私はこの種のことを行うことについて多くの情報を読んでおり、GORMのデフォルトは「belongsTo」と明示的な「マッピング」を使用しています。

「belongsTo」のドキュメントに基づいてこれを行う1つの方法は、Bookクラスの行を次のように変更することであるように思われました。

Author author

static belongsTo = [author:  Author]

これにより、作成者が関係の「所有側」であることを明示します。ドキュメントは、これが私が求めているカスケード削除動作を生成するはずであることを示唆しているようです。ただし、明示的な「hasMany = [books:Book]」をAuthorクラスに追加しない限り、機能しません。私はこれをしたくありません。(この願いは私の実際のビジネスドメインではより理にかなっていますが、理解の練習としても、Authorドメインクラスに本について明示的に知ってもらう必要がある理由はまだわかりません)。

Authorクラスを変更せずに、データベースに「カスケード削除」設定を生成するようにBookクラスを変更するgrails設定が欲しいのですが。次のような明示的なマッピングを使用してみました。

static mapping = {
        author cascade: 'all'
}

そして、これと他の明示的なマッピングまたは「belongsTo」オプションとの組み合わせ。これはうまくいきませんでした。

基盤となるSQLデータベースの「制約」を単純に変更するだけで、必要な動作が提供されることに注意してください。これをGrailsで取得する方法はありますか?そうでない場合、私はここで基本的なことを誤解しましたか、それとも愚かなことをしようとしていますか?

4

1 に答える 1

2

著者のBookタイプの必須フィールドが欠落していると思います。

これがサンプルコードです。これはドキュメントに従っています(テスト済みで動作します)

class Author {

    String name
    Book book //you are probably missing this field

    static constraints = {
    }
}

class Book {

    String name

    static belongsTo = [author: Author]

    static constraints = {
    }
}

テストケース:

@TestFor(Author)
@Mock([Book])
class AuthorTests {

    @Test
    void testAuthorBookCascades() {

        Author a = new Author(name: "Douglas Adams")
        Book b = new Book(name: "So Long, and Thanks for all the Fish")
        a.book = b
        a.save()

        assert Author.count() == 1
        assert Book.count() == 1

        a.delete()

        assert Author.count() == 0
        assert Book.count() == 0
    }
}

ご覧のとおり、AuthorのBook引数が必要です。hasManyまたはhasOne句は必要ありません。

于 2012-05-02T03:27:08.573 に答える