有这样的模型(简化):
case class User(id:Int,name:String)
case class Address(id:Int,name:String)
...
Slick(2.1.0版)表映射:
class Users(_tableTag: Tag) extends Table[User](_tableTag, "users") with WithId[Users, User] {`
val id: Column[Int] = column[Int]("id", O.AutoInc, O.PrimaryKey)
...
}
trait WithId[T, R] {
this: Table[R] =>
def id: Column[Int]
}
混合性状
WithId
我想为列 id: Column[Int]
的不同表实现通用 DAO 方法(我希望方法 findById
与 User
和 Address
表映射一起使用)trait GenericSlickDAO[T <: WithId[T, R], R] {
def db: Database
def findById(id: Int)(implicit stk: SlickTableQuery[T]): Option[R] = db.withSession { implicit session =>
stk.tableQuery.filter(_.id === id).list.headOption
}
trait SlickTableQuery[T] {
def tableQuery: TableQuery[T]
}
object SlickTableQuery {
implicit val usersQ = new SlickTableQuery[Users] {
val tableQuery: Table Query[Users] = Users
}
}
问题是
findById
不编译:Error:(13, 45) type mismatch; found : Option[T#TableElementType] required: Option[R] stk.tableQuery.filter(_.id === id).list.headOption
如我所见
T
类型为 WithId[T, R]
同时类型为 Table[R]
. Slick 实现了 Table
输入这样如果 X=Table[Y]
然后 X#TableElementType=Y
.所以在我的情况下
T#TableElementType=R
和 Option[T#TableElementType]
应推断为 Option[R]
但事实并非如此。我哪里错了?
最佳答案
您对 WithId[T, R]
的假设类型为 Table[R]
是错的。 WithId[T, R]
中的self类型注解只需要一个 Table[R]
混入,但这并不意味着 WithId[T, R]
是 Table[R]
.
我认为你混淆了 WithId
的声明带有 WithId
的实例最终需要是 Table
的一个实例.
您在 GenericSlickDAO
中的类型上限约束trait 也不保证 WithId
的属性(property)成为 Table
的一个实例,因为任何类型都是其自身的子类型。
见 this关于自我类型和子类型之间差异的更详细解释的问题。
关于使用 Slick Table 的 Scala 类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27413340/