使用 Slick Table 的 Scala 类型推断

标签 scala types slick type-inference

有这样的模型(简化):

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 方法(我希望方法 findByIdUserAddress 表映射一起使用)
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=ROption[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/

相关文章:

c++ - 为什么对基类子对象有限制?

types - 如何从 Int 派生出自己的区分类型?

postgresql - 如何在 Slick 中调用存储过程并获取返回值(使用 Scala)

json - Play Scala JSON 正文解析器默认值字段

scala - [喷客户端] : Facebook graph API returning wrong contentype

Scala 错误 : '=' expected but ';' found

scala - scalaz-stream 的 inflate 使用示例

Scala:值类 X 作为 X# 添加到其方法的返回类型

swift - 属性作为类中的函数类型

scala - 如何使用可空列编写光滑的表定义?