在Slick 2中,我们可以像这样映射表:
case class Cooler(id: Option[Int], minTemp: Option[Double], maxTemp: Option[Double])
/**
* Define table "cooler".
*/
class Coolers(tag: Tag) extends Table[Cooler](tag, "cooler") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def minTemp = column[Double]("min_temp", O.Nullable)
def maxTemp = column[Double]("max_temp", O.Nullable)
def * = (id.?, minTemp.?, maxTemp.?) <> (Cooler.tupled, Cooler.unapply _)
}
object Coolers {
val tableQuery = TableQuery[Coolers]
}
因为我有很多的表,我想为它们定义通用的方法,如find
,delete
,update
所以我必须要定义一个超类这些方法从哪里致以对象(object Coolers extends TableUtils[Coolers, Cooler]
)。为了定义这些方法,我需要tableQuery
移出该超类中的对象,因此我尝试了如下操作:
abstract class TableUtils[T <: Table[A] , A] {
val tableQuery = TableQuery[T]
}
但我收到tableQuery
定义错误:
class type required but T found
有人知道我在做什么错吗?
当您执行操作TableQuery[T]
时,实际上是在调用TableQuery.apply
,它实际上是一个宏。
该宏的主体尝试实例化T
,但是在您的情况下T已成为编译器不知道如何实例化的(未知)类型参数。问题类似于尝试编译它:
def instantiate[T]: T = new T
// Does not compile ("class type required but T found")
最终结果是TableQuery.apply
只能在具体类型上使用。
您可以使用类型类来TableQuery.apply
解决该问题,方法是使用类型类来捕获对调用的了解(在已知具体类型时),并使用隐式宏来提供此类型类的实例。然后,您将获得类似以下内容的信息:
abstract class TableUtils[T <: Table[A] : TableQueryBuilder, A] {
val tableQuery = BuildTableQuery[T]
}
whereTableQueryBuilder
是类型类,它BuildTableQuery
是该类的替代版本TableQuery.apply
,将转发给TableQueryBuilder
实例以执行实际的实例化。
仅声明tableQuery
为抽象值并在以下每个具体派生类中对其进行定义将更加容易(如果不太方便)TableUtils
:
abstract class TableUtils[T <: Table[A] , A] {
val tableQuery: TableQuery[T, T#TableElementType]
// define here your helper methods operating on `tableQuery`
}
object Coolers extends TableUtils[Coolers, Cooler] {
val tableQuery = TableQuery[Coolers]
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句