我正在探索如何使用最新的Slick 3.1.1来实现通用DAO以提高工作效率的不同可能性,是的,因为我的Play Web应用程序的服务层基于{{1}单独导致很多样板代码。我希望在我的通用DAO实现中使用的方法之一是TableQuery
,在Criteria API的帮助下可以在JPA中使用。就我而言,我正在使用Slick Code Generator从sql脚本生成模型类。
我需要以下内容才能动态访问取自Scala. Get field names list from case class:
的属性名称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
但这不起作用,因为我需要更好的Scala Kungfu。 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
}
是实体表类型,T
是作为案例类生成的行类型,因此是有效的Scala R
类型。
该代码中的第一个问题是效率太低,因为而不是做例如。
Product
正在做:
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")
函数时没有这种可能性?
答案 0 :(得分:1)
通过动态提供的列名实现过滤器和排序的最佳方法可能是纯SQL或扩展代码生成器以生成扩展方法,如下所示:
implicit class DynamicPersonQueries[C[_]](q: Query[PersonTable, PersonRow, C]){
def dynamicFilter( column: String, value: String ) = column {
case "firstName" => q.filter(_.firstName === value)
case "streetNumber" => q.filter(_.streetNumber === value.toInt)
...
}
}
您可能需要稍微调整一下类型才能使其编译(之后理想情况下更新此帖子)。)。
然后您可以按照以下所有提供的值进行过滤:
val examples: Map[String, String] = ...
val t = TableQuery[PersonTable]
val query = examples.foldLeft(t){case (t,(column, value)) => t.dynamicFilter(column, value)
query.result
此处解释了扩展代码生成器:http://slick.lightbend.com/doc/3.1.1/code-generation.html#customization
答案 1 :(得分:0)