我正在探索如何使用最新的Slick 3.1.1实现通用 DAO以提高生产力的不同可能性,是的,需要它,因为TableQuery
单独基于我的 Play Web 应用程序的服务层会导致大量样板代码. 我想在我的通用 DAO 实现中使用的方法之一是findByExample
, 在 JPA 中可能在Criteria API的帮助下。就我而言,我使用Slick Code Generator从 sql 脚本生成模型类。
我需要以下内容才能动态访问取自Scala 的属性名称。从案例类中获取字段名称列表:
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
,是作为案例类生成的行类型,因此是有效的 ScalaProduct
类型。
该代码中的第一个问题是效率太低,因为不是做例如
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
?