Slick 3.0.0 documentation - 15 Direct Embedding (Deprecated)
Permalink to Direct Embedding (Deprecated) — Slick 3.0.0 documentation
バージョン3.0から非推奨となるAPI
DirectEmbeddingはSlick1.0の頃に加えられた、実験的なクエリAPIであったが、バージョン3.0より非推奨となった。この機能はバージョン3.1に削除される予定だ。プロダクション環境などでは、Slickの標準的なクエリAPIを利用して欲しい。
Unlike the standard API, the direct embedding uses macros instead of operator overloading and implicit conversions for its implementation. For a user the difference in the code is small, but queries using the direct embedding work with ordinary Scala types, which can make error messages easier to understand.
direct embeddingは型検査のために実行時にScalaコンパイラにアクセスする必要がある。Slickは必要性に駆られない限り、アプリケーションに対し、依存性を避けるためにScalaコンパイラへの依存性を任意としている。そのため、direct embeddingを用いる際にはプロジェクトの build.sbt
に対し明示的にその依存性を記述しなくてはならない。
libraryDependencies <+= (scalaVersion)("org.scala-lang" % "scala-compiler" % _)
import slick.driver.H2Driver
import H2Driver.api.{Database, DBIO}
import slick.direct._
import slick.direct.AnnotationMapper._
スキーマは現在でえは行を保持しているケースクラスに対してアノテーションを付与する事で記述する事が出来る。今後、より柔軟にスキーマの情報を拡張出来るような機能を提供する予定だ。
// describe schema for direct embedding
@table(name="COFFEES")
case class Coffee(
@column(name="NAME")
name : String,
@column(name="PRICE")
price : Double
)
Queryableはテーブルデータに対しクエリの演算を行うためのものであり、注釈付けられた型引数を取る。
_.price
はここではInt型である。潜在的な、マクロベースの実装においてはmapやfilterに与えられた引数はJVM上で実行されないが、その代わりにデータベースクエリへと変換される事を覚えておいて欲しい。
// query database using direct embedding
val q1 = Queryable[Coffee]
val q2 = q1.filter( _.price > 3.0 ).map( _ .name )
クエリを実行するためには、選択したデータベースのドライバを用いるSlickBackendインスタンスを作成する必要がある。
val db = Database.forConfig("h2mem1")
try {
// execute query using a chosen db backend
val backend = new SlickBackend( H2Driver, AnnotationMapper )
println( Await.result(db.run(backend.result(q2)), Duration.Inf) )
println( Await.result(db.run(backend.result(q2.length)), Duration.Inf) )
} finally db.close
ImplicitQueryableを用いると、queryableはバックエンドとセッションに束縛される。クエリはその上で以下のような方法で簡単に実行する事が出来る。
//
val iq1 = ImplicitQueryable( q1, backend, db )
val iq2 = iq1.filter( c => c.price > 3.0 )
println( iq2.toSeq ) // <- triggers execution
println( iq2.length ) // <- triggers execution
direct embeddingは現在、 String
, Int
, Double
といった値に対しマッピングされるデータベースカラムのみをサポートしている。
QueryableとImplicitQueryableは現在、次のようなメソッドを用意している。
map, flatMap, filter, length
これらのメソッドはimmutableな演算を行うが、関数呼び出しによる変化を包含した新しいQuaryableを返す。
上記の関数におけるシンタックスとして、以下のオペレータを利用する事が出来る。
Any: ==
Int, Double: + < >
String: +
Boolean: || &&
他に定義された独自のオペレータについても、型検査がマッチしていれば利用する事が出来る。しかし現時点では、それらのオペレータは実行時に失敗するクエリを生成するようなSQLへ変換する事が出来ない。(例: ( coffees.map( c => c.name.repr ) )
)将来的には、コンパイル中にそのようなものもキャッチするような方法を検討している。
クエリは行を補完するようなオブジェクトを保持する、任意にネストされたタプルのシーケンスを結果として返す。
q1.map( c => (c.name, (c, c.price)) )