Help us understand the problem. What is going on with this article?

スタンドアローンGORMをGroovyスクリプトからシュっと利用する

More than 1 year has passed since last update.

G* Advent Calendar 2017 20日目の記事です。

GrailsのO/Rマッピングライブラリである「GORM」は、Grailsから切りはなして単体で使用することもできます。これをスタンドアローンGORMと呼びます。

非WebアプリやGrails以外の他のフレームワークから高機能なORMとして使うことも可能ですし、Grailsでのシステム開発の一部として、バッチやシェルスクリプトやsshでキックしたいとか、シェルアカウントの管理者権限者だけがデータベースにアクセスしたいときには、スタンドアローンGORMが有用なケースがあります。

というのも、そういうケースでは以下のような選択肢があるにはあるのですが、いずれも固有の課題を抱えているからです。

  1. grails scriptsとしてGrailsサービスやGrailsドメインクラスを呼び出す処理などを記述し、Grailsのプロジェクトフォルダ(GRAILS_PROJ/scriptsを含む)に格納して、grailsコマンドで起動。 問題は、プロジェクトソースコードを運用環境に展開しておく必要があること。
  2. DB処理をWeb APIとして公開して、それを叩くクライアントを開発する。 転送速度がネックになったり、ポートを公開することでセキュリティの問題になるかもしれない。
  3. Service層をGrailsのRemoting Pluginを使って公開する。 問題は同上。
  4. SQLを叩く別プログラムを開発する(Groovy SQL, ..)。 この場合の問題は、GrailsのドメインクラスからDDL生成されたデータベースに対して、生SQLを書くのはかったるいだけではなく、ドメインクラスの制約(constraint)の処理を別途しなければならないということ。

それぞれのケースで示した問題が許容できないとき、スタンドアローンGORMが有用です。

さて、具体的な使用方法としては、Spring Bootのアプリケーションから呼び出すこともできるでしょう。
本記事では、もっとストレートに素のGroovyスクリプトからGORMを呼び出す例を紹介します。

方法

たとえば、こんな感じでGroovyスクリプトを書いて、

@Grab('org.grails:grails-datastore-gorm-hibernate5:6.1.0.RELEASE')
@GrabExclude('javax.transaction:jta')
@Grab('com.h2database:h2:1.4.192')
@Grab('org.apache.tomcat:tomcat-jdbc:8.5.0')
@Grab('org.slf4j:slf4j-log4j12')
import java.lang.String
import org.grails.orm.hibernate.HibernateDatastore
import grails.gorm.annotation.Entity

@Entity
class Book {
    String title
    static hasMany = [authors: Author]
    String toString() {"$id: $title"}
}

@Entity
class Author {
    String name
    static hasMany = [books: Book]
    static belongsTo = Book
    String toString() {"$id: $name"}
}

def hibernateDatastore = new HibernateDatastore([
        'hibernate.hbm2ddl.auto': 'create-drop',
        'dataSource.driverClassName': 'org.h2.Driver',
        'dataSource.url': 'jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE',
        'dataSource.username': 'sa',
        'dataSource.password': '',
    ],
    Author)

Author.withTransaction {
    Author a = new Author(name:'上原 潤二');
    Book b1 = new Book(title: 'プログラミングGROOVY').addToAuthors(a).save()
    Book b2 = new Book(title: 'Grails徹底入門').addToAuthors(a).save()
    println Book.findByTitleLike('G%')
}

GroovyおよびJDKがインストールされていれば、以下で実行できます。

> groovy groovyスクリプトファイル名

GroovyやJDK以外の何かを事前ダウンロードしたりインストールしたりフォルダ構成を考えたりコンパイルしたりビルドしたりビルドスクリプトを書いたりデプロイしたりパッケージングしたりが一切不要なのが利点です✌。

なお、上記では@Entityでドメインクラスを定義していますが、データベースがGrailsアプリケーションの一部であるなら、Grailsアプリケーション本体のwar(やjar)に含まれるドメインクラスのクラスファイルのjarをクラスパスに含めれば別に書かなくても利用可能です(多分)。

uehaj
Groovy、Grails、Haskell、Elm, Rust, ES2015, Dart, React, Fregeが好き。
http://d.hatena.ne.jp/uehaj/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした