ScalaのORMapperのSquerylを試してみてハマった3つのこと

August 16, 2011 - Scala

ScalaのORMとしてSquerylってのがあります。

使い方は上記リンク先を見ればだいたいわかります。

あと、@jugyoさんのブログに導入あたりはまとまっていますし、つまづいたらGoogleGroupで検索すれば何か見つかるかもしれません。

さて、今回はTwitterっぽいものを想定して機能を試してみたのですが、3つほどハマったところを記しておきます。

環境はScala2.9.0.1、Sbt0.7.7、MySQL5.5、Squeryl0.9.4です。

ソースはgistに登録。それを本文末尾にも掲載しておきました。

1.プライマリーキーの指定での嵌りどころ

1つのカラムがPKとなるテーブルスキーマの場合、org.squeryl.KeyedEntity[T]を継承して使います。


class Users(id: Long, text: String) extends KeyedEntity[Long]

KeyedEntityにはidというフィールドが用意されていて、継承時に型を指定することで、PKの型に適用させることができます。今回の場合であればLong型のPK「id」ということになります。

ただし、この場合、PKはautoincrementedになってしまいます。

コード的には下記のようにKeyedEntity[T]を使わずSchema継承時に定義するのと同等になるわけです。


class Users(id: Long, text: String)

class Db extends Schema {

  val users = table[User]("users")

  on(users)(u => declare(

    u.id is (primaryKey, autoincremented))

}

これは結構困ります。そんな場合はSchemaを継承するときに定義を上書きすればOK。


class Users(id: Long, text: String) extends KeyedEntity[Long]

class Db extends Schema {

  val users = table[User]("users")

  on(users)(u => declare(

    u.id is (primaryKey))

}

これはSquerylのGoogleGroupに書いてました。

2.DDLのカラムの順番の嵌りどころ

Db.printDdlを実行した時にカラムの順番が予測できません。

PKが最初にくるのかと思えばそうでもないみたい。ここは細かく追ってないですが、これもGoogleGroupに答えがありました。

答えとしては、org.squeryl.internals.DatabaseAdapter:: writeCreateTableあたりをorverrideしてなんとかしてくれとのこと。

https://github.com/max-l/Squeryl/blob/master/src/main/scala/org/squeryl/internals/DatabaseAdapter.scala#L255

なんか良い方法はないの…

とりあえず、printDdlした結果をコピーして、順番だけ書き換えて、手動で直接DBにクエリ発行すればなんとかなるでしょう。

3.外部キーの利用でのはまりどころ

2つのテーブルにRelationを設定してからDb.createした際、外部キーが設定されない問題がありました。

MySQLは5.5を使っているので外部キーに対応していない訳でもないです。

問題はAdapterの選定にありました。

org.squeryl.adapter.MySQLAdapter

をつかっていたのですが、

org.squeryl.adapter.MySQLInnoDBAdapter

を使えばOKでした。

根本の原因は、org.squeryl.adapter.MySQLAdapterに


override def supportsForeignKeyConstraints = false

と定義してあり、一方のorg.squeryl.adapter.MySQLInnoDBAdapterには


override def supportsForeignKeyConstraints = true

と定義してあります。

この値がtrueになっていないとForeignKeyの制約がDDLに含まれなくなってしまうので注意です。

Docコメントにも書いてあるので注意です。

以上、Squerylを弄ってみて嵌ったことをまとめてみました。

Squerylの使用感

ちょっと前にTwitterのStreamAPIのデータをMySQLに格納するためにSquerylを使ったのと今回少し弄ってみただけなのでまだまだ知らないことだらけです。他にも機能的はたくさん用意されていると思いますし、APIも割となじみやすいので複雑すぎないテーブル定義の場合には積極的にSquerylを使っていこうと思います。

※ドキュメントや本体のソースを追いかけたりしながら使い方を学ぶのは非常に楽しいです:)

で、ソースは以下です。