ScalaのORMapperのSquerylを試してみてハマった3つのこと
August 16, 2011 - Scala
ScalaのORMとしてSquerylってのがあります。
使い方は上記リンク先を見ればだいたいわかります。あと、@jugyoさんのブログに導入あたりはまとまっていますし、つまづいたらGoogleGroupで検索すれば何か見つかるかもしれません。
- Twiwt:Blog / jugyo : squeryl を試す
- Twiwt:Blog / jugyo : Squeryl の使い方 - セットアップ, モデルの定義, テーブル作成
- Squeryl | Google Groups
環境は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してなんとかしてくれとのこと。なんか良い方法はないの…
とりあえず、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を使っていこうと思います。※ドキュメントや本体のソースを追いかけたりしながら使い方を学ぶのは非常に楽しいです:)
で、ソースは以下です。