ドメインクラスGORM
永続化するためのモデルをGrailsではドメインクラスと呼ぶ。ドメインクラスには、必要なプロパティと制約、ORマッピングの定義をするマッピングDSL等を記述する。記述した定義をもとに、Hibernateの定義、テーブルの生成等を自動で行ってくれる。
データ参照には、ダイナミックファインダ、クライテリアビルダ等、Groovy DSLを活用した仕組みで操作できる。もちろんHibernateをベースに実装されているので、HQL(Hibernateクエリ言語)も利用できる。
ドメインクラスと、参照の仕組みのを、GORM ( ゴーム Grails O/R マッピング)という。本稿では、生成・参照の一部を紹介する。なお、詳細は公式リファレンスを参照して頂きたい。
ドメインクラス生成コマンド
% grails create-controller com.example.Book (パッケージ名から生成したいドメイン名称を指定)
Book.groovy
package com.example
class Book {
//マッピングDSL:テーブル名、データ型の指定等が行える。
static mapping = {
id generator:'sequence', params:[sequence:'book_id_seq']
columns {
comment sqlType:'varchar(4000)'
}
}
//プロパティ:テーブルのフィールド名としても使用される。
//いちばんシンプルなドメインクラスは、この部分のみ記述するばよい。
String title
String author
String comment
//制約:バリデーション、ビューでの自動生成されるフォーム用情報にも使われる。
static constraints = {
title nullable:false,blank:false
author nullable:false,blank:false
comment nullable:false,blank:false,maxSize:4000
}
}
GORM / データ操作
データ操作用の機能などは、動的に追加されたメソッドを使用する。実装方法については、以下のサンプルコードを参照して頂きたい。
def book = new Book()
book.title = 'Grails徹底入門'
// .... 省略 ....
//保存を行う
book.save()
// データの取得
book.get(1) // idを指定して取得
book.getAll(7,5,8) //複数idを指定して取得
book.list() // 全リスト
//データの削除
def book = Book.get(1)
book.delete()
GORM / ダイナミックファインダ
ダイナミックファインダとは、メソッドをキャメルケースで検索したいフィールド名や、その条件を指定してクエリが記述できる仕組みだ。内部的にメソッド名を変換して、動的にクエリが解釈され実行される。
説明用の例として、以下のドメインクラスを使用する。
class Book {
String title
Date releaseDate
Author author
}
ドメインクラスBookに対しての、ダイナミックファインダの記述。
def book = Book.findByTitle("Grails 徹底入門")
def books = Book.findAllByTitleLike("Groovy%")
book = Book.findByReleaseDateBetween( firstDate, secondDate )
book = Book.findByReleaseDateGreaterThan( someDate )
book = Book.findByTitleLikeOrReleaseDateLessThan( "%Something%", someDate )
c = Book.countByReleaseDateBetween(firstDate, new Date())
def results = Book.listOrderByTitle(max:10)
ご覧の通り、ダイナミックファインダは、findBy、findAllBy、listOrderBy、countByで始まり、フィールド名と条件などをつなげて記述する。詳細は公式ドキュメントを参照してほしい。
GORM / クライテリアビルダ
クエリをDSLで記述する、もう一つのGrailsでのクエリ発行方法がクライテリアビルダだ。この内容も詳しくは公式ドキュメントを参照してほしい。
def c = Account.createCriteria()
def results = c {
between("balance", 500, 1000)
eq("branch", "London")
or {
like("holderFirstName", "Fred%")
like("holderFirstName", "Barney%")
}
maxResults(10)
order("holderLastName", "desc")
}