最新のSlick 3.1.1を使用して汎用DAOを実装する方法については、生産性を高めるためにさまざまな可能性を模索していますが、そのためには、Play Webアプリケーションのサービスレイヤーを基にしてTableQuery
をベースにすると、 。ジェネリックDAO実装で特色にしたいメソッドの1つはfindByExample
であり、Criteria APIの助けを借りてJPAで可能です。私の場合は、Slick Code Generatorを使用してSQLスクリプトからモデルクラスを生成しています。Slick:一般的な例findByExampleで実装する方法
:
import scala.reflect.runtime.universe._
def classAccessors[T: TypeTag]: List[MethodSymbol] = typeOf[T].members.collect {
case m: MethodSymbol if m.isCaseAccessor => m
}.toList
findByExample
案の実装は次のようになります。
def findByExample[T, R](example: R) : Future[Seq[R]] = {
var qt = TableQuery[T].result
val accessors = classAccessors[R]
(0 until example.productArity).map { i =>
example.productElement(i) match {
case None => // ignore
case 0 => // ignore
// ... some more default values => // ignore
// handle a populated case
case Some(x) => {
val columnName = accessors(i)
qt = qt.filter(_.columnByName(columnName) == x)
}
}
}
qt.result
}
しかし、これは動作しません。私はScala Kungfuがもっと必要なので。 T
はエンティティテーブルタイプであり、R
はケースクラスとして生成される行タイプであるため、有効なScala Product
タイプです。
このコードの第1の問題は、たとえばコードを実行する代わりに、あまりにも効率が悪いことです。
qt.filter(_.firstName === "Juan" && _.streetName === "Rosedale Ave." && _.streetNumber === 5)
がやっている:
// find all
var qt = TableQuery[T].result
// then filter by each column at the time
qt = qt.filter(_.firstName === "Juan")
qt = qt.filter(_.streetName === "Rosedale Ave.")
qt = qt.filter(_.streetNumber === 5)
第二に、私は動的に私が代わりに
を持っている必要がありますqt.filter(_.firstName == "Juan")
すなわちフィルタ方式では、列名にアクセスする方法を見ることができません
qt.filter(_.columnByName("firstName") == "Juan")
しかし、明らかにfilter
機能を使用している間、そのような可能性はありませんか?