SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Groovy+GrailsでRailsなWeb開発

Grailsのバリデーションとリレーションシップ

Groovy+GrailsでRailsなWeb開発 第4回

  • X ポスト
  • このエントリーをはてなブックマークに追加

リレーションシップ

 データベースを利用する場合、いくつかのテーブルを関連付けて利用することもあります。SQLでは「JOIN」というものを使い、複数のテーブルを結合して扱うことができました。こうした複数テーブルの関連付けは、Grailsでは「リレーションシップ」と呼ばれています。

 リレーションシップの設定は非常に簡単です。ドメインクラスに、そのためのstaticなプロパティを用意しておくだけです。リレーションシップの種類と、用意されているstaticプロパティの関係を以下に整理しましょう。

1対多対応「hasMany」

 あるテーブルのレコード1つに対し、別のテーブルのレコードが複数対応するという形の結合です。これは、1対多の「1」の側(主テーブル)に「hasMany」を用意し、「多」の側(従テーブル)のテーブルを関連付けます。

 hasManyは、両者の間に密接なつながりが構築されます。例えば、hasManyを用意しているテーブル(主テーブル)のレコードを削除すると、もう1方の従テーブルからも、そのレコードに関連付けられたレコードがすべて削除されます。

多対1対応「belongsTo」

 あるテーブルの複数のレコードに対し、別のテーブルのレコード1つが対応するという形の結合です。これは、先ほどのhasManyを逆に設定すれば同じような働きをすることは可能なのですが、hasManyは非常に密接な関連付けがされ、主のテーブルのレコードを削除すると従側も削除されます。

 このbelongsToは、多対1の「多」の側(従テーブル)に配置します。これにより、そのテーブルが、もう1方のテーブルに従属するものとして機能するようになります。従属する側に設定されますから、こちらのテーブルのレコードを削除しても、もう片方のテーブルのレコードは削除されません。

1対1対応

 常にあるテーブルの1レコードが別のテーブルの1レコードに対応するという結合です。これは、1対多対応の「hasMany」をそのまま応用してできます。対応する複数のレコードから1つだけをピックアップするように考えればよいのです。もし「完全に、常に1対1でしかレコードが存在できないようにしたい」ということであれば、従属するテーブル側に用意する「結合する主テーブルのフィールド」(後述のCommentsドメインクラスの項目を参照ください)の値をユニークであるようにバリデーション設定し、同じものに結合するレコードが作れないようにすればよいでしょう。

多対多対応

 あるテーブルの複数レコードに対し、別のテーブルの複数レコードが対応するという形の結合です。これは、「hasMany」と「belongsTo」を組み合わせることで可能です。両方のテーブルに、1対多対応の「hasMany」を用意し、さらにどちらかに「belongsTo」を用意するのです。hasManyだけでは、どちらが主テーブルでありどちらがそれに従属するものかが分かりません。belongsToを用意することで、両者の主従関係が明確になります。

Commentsドメインクラスの作成

 では、実際にテーブルの結合がどのように行われるのか試してみましょう。ここでは、Boardsに投稿された記事につけられるコメントを管理する「Comments」テーブルを用意することにしましょう。これは、ざっと次のような項目をもちます。

項目 説明
ID 整数値。プライマリキーとして用意します。
BOARD 関連するBoardsのインスタンスを保管します。
NAME 文字列。投稿者名を保管します。
MESSAGE 投稿したコメントを保管します。

 リレーションシップで2つのテーブルを関連付ける場合、従属するテーブル側に、結合する主テーブルのレコードを保管するためのフィールドを用意します。ここでは、BoardsにCommentsを関連付けますので、このようにComments側に、関連付けられるBoardsオブジェクトを保管するフィールドを用意しておくわけです。

 では、実際にCommentsを作成しましょう。ここでのサンプルでは、データベースプログラムにHSQLDBを利用していますから、特にテーブルの準備などは不要です。ドメインクラスを作成するだけです。

Comments.groovyのソースコード
class Comments {
    Long id
    Boards board // 結合されるBoardsを保管する
    String name
    String message

    static belongsTo = Boards

    static constraints = {
        message(blank:false)
    }
}

 Commentsは、Boardsに従属しますので、belongsToを用意しておきます。また、constraintsを使い、messageは必須項目に設定しておきましょう。idはプライマリキーとして自動設定されますからconstraintsに用意する必要はありません。またboardも、後述しますがhasManyで強い関連付けがされる場合、自動的に必須項目として扱われますのでconstraintsは不要です。

Boardsドメインクラスの修正

 では、Boardsドメインクラス側も修正しましょう。こちらは、hasManyを追加するだけです。

class Boards {
    Long id
    String name
    String title
    String content

    static hasMany = [comments:Comments] //★追加

    static constraints = {
        name(blank:false)
        title(blank:false)
    }
}

 ここでは、hasManyの値として[comments:Comments]という値が設定されていますが、これはCommentsを「comments」という名前で連携させる、ということを意味します。これにより、結合されて取り出されたCommentsのレコードは、Boardsのcommentsとして得られるようになります。

 先のbelongsToでは、単に名前を文字列で指定するだけでした。こちらは、結合された主テーブルのレコードをboardとして保管していますから、別途変数などを用意する必要もなく、ただ「どのドメインクラスと関連があるのか」さえ指定すればよかったのです。が、hasManyの設定では、関連するCommentsを保管する用意などはありませんから、このように「プロパティ名:結合するドメインクラス名」という形で記述をします。

次のページ
CommentsControllerの作成

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Groovy+GrailsでRailsなWeb開発連載記事一覧

もっと読む

この記事の著者

掌田 津耶乃(ショウダ ツヤノ)

三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3916 2009/05/27 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング