使用traits的光滑映射表会引发异常

时间:2015-12-03 18:11:56

标签: scala slick slick-3.0

我试图在光滑的3.1.0中使用traits来定义映射表。由于官方文档中没有提到任何内容,我甚至不确定这是否可行。以下是我到目前为止的情况:

表格定义:

class PersonTable(tag: Tag) extends Table[PersonModel](tag, "person") {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
  def firstName = column[String]("first_name", O.Length(PersonDb.FirstNameColumnLength))
  def lastName = column[String]("last_name", O.Length(PersonDb.LastNameColumnLength))

  def * = (id.?, firstName, lastName) <> (PersonModelImpl.tupled, PersonModelImpl.unapply _)
}

PersonModel:

trait PersonModel {
  def id: Option[Int]
  def firstName: String
  def lastName: String
}

PersonModelImpl:

case class PersonModelImpl(
    override val id: Option[Int],
    override val firstName: String,
    override val lastName: String)
  extends PersonModel

编译上面的代码会导致错误:

Compilation error[type mismatch;
  found   : slick.lifted.MappedProjection[models.PersonModelImpl,(Option[Int], String, String]
  required: slick.lifted.ProvenShape[models.PersonModel]]

但是,在表格定义中将...extends Table[PersonModel]...更改为...extends Table[PersonModelImpl]...可以完美无缺地工作。

基本上我的问题是:

  1. 是否可以在映射表中使用特征TableElementType
  2. 如果是的话,我做错了什么?

1 个答案:

答案 0 :(得分:1)

数目:

  1. 是的,但需要具有正确的投影功能(*)。
  2. *上的类型错误。为了使隐式解析到正确的MappedProjection,类型必须完全匹配。
  3. 您应该可以通过执行以下操作来解决这两个问题:

    def * = {
      val applyAsPersonModel: (Option[Int], String, String) => PersonModel =
        (PersonModelImpl.apply _)
      val unapplyAsPersonModel: PersonModel => Option[(Option[Int], String, String)] =
        { 
          // TODO: Handle any other subclasses of PersonModel you expect.
          case personImpl: PersonModelImpl => PersonModelImpl.unapply(personImpl)
        }
      (id.?, firstName, lastName) <> (applyAsPersonModel.tupled, unapplyAsPersonModel)
    }
    

    请注意TODO。如果您尝试插入任何非PersonModelImpl实例,除非向该部分函数添加其他case语句,否则您将收到异常。或者,您可以创建一个新的PersonModelImpl实例以传递给unapply

    val unapplyAsPersonModel: PersonModel => Option[(Option[Int], String, String)] =
      { person: PersonModel =>             
        PersonModelImpl.unapply(
          PersonModelImpl(person.id, person.firstName, person.lastName)
        )
      }