告诉 scala 编译器类型 TableQuery[T] 可以映射到具有属性 id 的东西的 way/s 是什么

What are the way/s of telling scala compiler that type TableQuery[T] can map to somthing has the attribute id

我希望编译器知道或测试该类型 T 是否具有 属性 id。

def del[T](id: Int) = TableQuery[T] filter (_.id === id) delete

trait T { val id: Int} 您的数据类型应该扩展 T。 您是否要删除所有 id=someId 的那些? 那样的话 filter(_.id === id).foreach(delete)

创建 Entity 特征的 T 子类型并在 Entity

中声明 id
 trait Entity {
  val id: Int
}

def del[T <: Entity](id: Int) = TableQuery[T] filter (_.id === id) delete

Scala REPL

scala> trait Entity {
     |   val id: Int
     | }
defined trait Entity

scala> def foo[T <: Entity](a: T) = a.id
foo: [T <: Entity](a: T)Int

您可以使用结构类型对类型参数实施约束。

case class Thing(id: Int)
def getId[A <: {val id: Int}](a: A):Int = a.id
println(getId(Thing(100)))

这里的结果是 100

但是,由于结构类型使用反射,因此这种方法会影响性能。

另外,正如 Ian 指出的那样,您需要在 scalaOptions 中打开 -language:reflectiveCalls

其他答案在某种程度上是正确的,但我怀疑它们是否适用于 Slick,您的 ID 必须是某个参数的 Rep 而不是 Int,最好的方法是带有 id 字段的抽象 table 并使您的具体 table 扩展:

abstract class RichTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
  val id: Rep[Long] = column[Long]("id", O.PrimaryKey, O.AutoInc)
}

class ConcreteTable(tag: Tag) extends RichTable[ConcreteRow](tag, "concrete_table") { ... }

请注意,我将 id 设为主键。现在任何 TableQuery[T][T <: RichTable[A], A] 都可以访问一个 id:

trait GenericPersistence[T <: RichTable[A], A] {

  val tableReference: TableQuery[T]

  def deleteById(id: Long)(implicit s: Session): Boolean = 
    tableReference.filter(_.id === id).delete == 1

  /* other generic methods ids based */
}

有关其他方法的更完整答案,您可以查看 this,对于 Slick 3,它基本相同。

你可以通过以下特征获得相同的结果:

trait RichTable[T] {
  self: Table[T] =>

  val id: Rep[Long] = column[Long]("id", O.PrimaryKey, O.AutoInc)
}

class ConcreteTable(tag: Tag) extends Table[ConcreteRow](tag, "concrete_table") with RichTable[ConcreteRow]

您可以决定是否要在特征中实现 id 字段。

仅供记录,我也尝试过这个,这似乎有效,但到目前为止我不相信实际代码中的进一步解决方案,因为这与用例相关。

trait TableModel[T <: ({val id: Rep[Int]}) with Table[U], U]{

    val tq: TableQuery[T]
    def del(id: Int) = tq filter (_.id === id) delete
   ...
}