Slick 3.0.0 documentation - 08 Schema Code Generation
Permalink to Schema Code Generation — Slick 3.0.0 documentation
データベーススキーマが既に存在している場合、Slickのコードジェネレータは非常に便利なツールとなる。これはジェネレータ単独で利用する事もできるし、sbtのbuildと組み合わせて必要な全てのSlickのコードを生成する事が出来る。
デフォルトでは、コードジェネレータは全てのテーブルに対するTable
クラスと、対応するTableQuery
の値を生成する。列に対応するものは、各カラムを引数に取るケースクラスとして生成される。22より多くのカラムを持つテーブルについては、コードジェネレータは自動的にSlickの実験的な機能であるHList
を用いた実装に変更する。これはScalaのタプルサイズ問題を解決する1つの方法である。(Scalaのバージョンが2.10.3以下である場合、コンパイル時間に対する問題を解決するためにHCons
が::
の代わりに用いられるが、これはScala2.10.4以上では解決されている話だ)
ジェネレータについては、talk at Scala eXchange 2013にも説明があるから、是非見て欲しい。
SlickのコードジェネレータはそのライブラリがSlick本体とは独立して公開されている。sbtプロジェクトにおいては、以下のような記述をビルド定義(build.sbt
やproject/Build.scala
など)に加える事で利用可能となる。
libraryDependencies += "com.typesafe.slick" %% "slick-codegen" % "3.0.0"
Mavenプロジェクトには、以下のような<dependency>
を加えて欲しい。
<dependency>
<groupId>com.typesafe.slick</groupId>
<artifactId>slick-codegen_2.10</artifactId>
<version>3.0.0</version>
</dependency>
Slickのコードジェネレータはコマンドラインから、もしくはJavaやScalaからAPIを利用して使う事が出来る。単純な例だと、以下のように実行すれば良い。
slick.codegen.SourceCodeGenerator.main(
Array(slickDriver, jdbcDriver, url, outputFolder, pkg)
)
もしくは、こんな感じに。
slick.codegen.SourceCodeGenerator.main(
Array(slickDriver, jdbcDriver, url, outputFolder, pkg, user, password)
)
引数は、以下のようなものを取る。
コードジェネレータはsbtで手で実行したり、コンパイル前に毎度実行したりも出来る。slick-codegen-exampleに例があるから参考にして欲しい。
(訳注: tototoshi/sbt-slick-codegenも参考までに)
デフォルトでは、生成されたコードは指定されたフォルダ以下にTables.scala
という名前のファイルで保存される。このファイルは、良い感じにインポート出来るコードを持つobject Tables
を含んでいる。Slickドライバが適切なものになっているかも確認出来る。このファイルにはtrait Tables
も含まれていて、Cakeパターンを用いたい場合にはこちらを利用すると良い。
Warning
生成されたコードを用いる際には、異なるデータベースドライバを誤って混ぜてしまわないように注意して欲しい。デフォルトの
object Tables
はコード生成の際にドライバを用いる。異なるドライバを一緒に使ってしまうと、ランタイムエラーを引き起こす。生成されたtrait Tables
は異なるドライバにより用いられるが、これは現在テストされておらず非公式な使い方となっている。あなたの環境では上手く動かないかもしれない。将来的にこれらについては公式でサポートする予定だ。
ジェネレータはデータモデルに対しどんなコードも生成出来るよう、様々なメソッドをオーバライドして自由にカスタマイズすることが出来る。簡単なカスタマイズから非常に大きなカスタマイズまで、様々なカスタマイズに対応出来る。Playに対応するフレームワークバインディングを行うだとか、そのような例がある。
This exampleでは、どのようにしてコードジェネレータをカスタマイズするのか、sbtのmulti-projectに対しどのようにセットアップするのか、メインとなるソースに対して、コンパイル前に毎度コードジェネレータをどのようにして実行させるのかを見ることが出来る。
コードジェネレータは、異なるフラグメントに対して最適化された小さなサブジェネレータの階層を構造化して実装されている。サブジェネレータの実装は、個々のファクトリメソッドをオーバーライドすることで、カスタマイズしたものに取り替える事ができる。SourceCodeGeneratorは各々のテーブルのためのサブジェネレータを生成するファクトリメソッドを含んでいる。サブジェネレータはTableクラス自体、エンティティとなるケースクラス、カラム、キー、インデックスなど、様々なものを生成するサブジェネレータを含んでいる。カスタマイズされたサブジェネレータも簡単に同様に扱う事ができる。
様々なサブジェネレータにおいて、Slickのデータモデルに関連する部分はコード生成を実行させる際にアクセスされる。
カスタマイズ可能なオーバーライド出来るメソッド一覧については、api documentationを見て欲しい。
以下にジェネレータをカスタマイズするサンプルを載せる。
import slick.codegen.SourceCodeGenerator
// データモデルを取得する
val modelAction = H2Driver.createModel(Some(H2Driver.defaultTables)) // テーブルのフィルタリングはここで行う
val modelFuture = db.run(modelAction)
// コードジェネレータをカスタマイズする
val codegenFuture = modelFuture.map(model => new SourceCodeGenerator(model) {
// マッピングするテーブルとクラス名をオーバーライド
override def entityName =
dbTableName => dbTableName.dropRight(1).toLowerCase.toCamelCase
override def tableName =
dbTableName => dbTableName.toLowerCase.toCamelCase
// いくつか追加のimportを加える
override def code = "import foo.{MyCustomType,MyCustomTypeMapper}" + "\n" + super.code
// テーブルジェネレータをカスタマイズ
override def Table = new Table(_){
// エンティティクラスの生成を抑制する
override def EntityType = new EntityType{
override def classEnabled = false
}
// カラムジェネレータをカスタマイズ
override def Column = new Column(_){
// 特定のカラムに対して、Scalaの型を変更するようカスタマイズ
// e.g. to a custom enum or anything else
override def rawType =
if(model.name == "SOME_SPECIAL_COLUMN_NAME") "MyCustomType" else super.rawType
}
}
})
codegenFuture.onSuccess { case codegen =>
codegen.writeToFile(
"slick.driver.H2Driver","some/folder/","some.packag","Tables","Tables.scala"
)
}