概要
下書きが溜まってしまったのでとりあえず投稿。そのうち文章とか修正予定。
GrailsはDataSource.groovyの中の各環境(dev, test, prod)にそれぞれ定義されたdataSource
の定義に従ってデータベースに接続してくれます。
普段はそれでいいのですが、ある特定のデータを取得するときだけは別のデータベースに繋ぎたい場合はどうすればいいのでしょうか?
通常は自分自身が利用するデータベースは一つだけですが、やはり要件によっては別のシステムのデータベースにアクセスしてデータを取得しなければならない、という状態は当然想定されます。
今回、独自のdataSourceを定義して、それをServiceの中から利用する方法を調べたのでメモします。
オリジナルのdataSourceの定義方法
オリジナルのdataSourceの定義自体はすごく簡単で、対象の環境(dev, test, prod)の中で、
dataSource_オリジナルの任意の名前
という書式で定義します。
dataSource_は固定です。
例えば以下のような感じ。
development {
dataSource {
dbCreate = "create-drop"
url = "jdbc:postgresql://localhost:5432/postgesqldb"
}
dataSource_mysql {
dialect = org.hibernate.dialect.MySQLInnoDBDialect
driverClassName = 'com.mysql.jdbc.Driver'
username = 'mysqluser'
password = '******'
url = 'jdbc:mysql://localhost/mysqldb'
}
}
JDBCドライバどうすんの?って話ですが、それはGrailsのBuildConfig.groovyのdependenciesに定義してしまえばOKです。非常にシンプル!
独自のdataSourceをServiceの中で使う
ここが落とし穴で、公式ドキュメントなどには、Serviceクラスの中で、以下の様に宣言するようにと説明されていますが、単純にServiceからgroovy.sql.Sqlを使いたい場合はコレではダメです。
class DataService {
// 独自dataSourceのアンダーバー以降を指定する
static datasource = 'mysql'
def serviceMethod() {
// groovy.sql.Sqlのコンストラクタにはこの場合'mysql'というStringが渡されることになる。
// でもStringを取るgroovy.sql.Sqlのコンストラクタは無いので当然例外。
def sql = new Sql(dataSource)
def query = """
SELECT COUNT(*) FROM hoge
"""
println sql.rows(query)
}
以下のようにする必要が有ります。
class DataService {
Sql sql
// 独自dataSource用のセッターを宣言する。
// 独自dataSource名の先頭にsetをつけて、先頭文字を大文字にするだけ。
void setDataSource_mysql(dataSource) {
sql = new Sql(dataSource)
}
def serviceMethod() {
def query = """
SELECT COUNT(*) FROM hoge
"""
println sql.rows(query)
}
GORMからも同じように別のデータベースにアクセスできるようですが、それはまた別の機会に調べたいと思います。
参考
5 Configuration 2.4.4
Grails User (Old Archive) - Using multiple datasources
[Grails]servicesで直接SQLを実行する方法
Sql (Groovy 2.2.1)