缺少OptionMapper,用于在光滑1.0中连接自定义映射的id类型

时间:2013-08-06 23:22:54

标签: scala slick

TL; DR:为什么不编译? https://github.com/refried/typedids-option-fk-issue


我正在使用Slick访问Oracle数据库。我尝试以cvogt的scaladays2013示例的方式实现自定义ID类型(例如UserID,AgencyID)以获得更安全的查询。但是当我尝试为FK加入时:

package controllers

import model._
import scala.slick.session.Database.threadLocalSession
import com.typesafe.slick.driver.oracle.OracleDriver.simple._


object Auth {
  def auth(username: String, password: String): Boolean = {
    val q = for {
      (u,s) <- User leftJoin Agency on (_.agencyId is _.id)
      if u.name.toLowerCase === username.toLowerCase.trim && u.password === fn_hash(password)
    } yield (s.dataOutOfDate.?.getOrElse(false))

    db withSession {
      q.list.map {
        case (agencyOutOfDate) => !agencyOutOfDate
      }.headOption.getOrElse(false)
    }
  }
}

我收到错误,我不知道如何解决。

Auth.scala:11: Cannot perform option-mapped operation
[error]       with type: (Option[model.AgencyId], model.AgencyId) => R
[error]   for base type: (model.AgencyId, model.AgencyId) => Boolean
[error]       (u,s) <- User leftJoin Agency on (_.agencyId is _.id)

当我为所有列使用相同的映射ID类型时,我没有任何问题:

case class ID(bytes: Array[Byte]) extends AnyVal
object ID {
  implicit val typemapper = MappedTypeMapper.base[ID,Array[Byte]](_.bytes, ID.apply)
}

虽然今天,我甚至无法复制/编译它。我错过了什么?这是我的模型来源:

import play.api.db.DB
import play.api.Play.current // implicit Application
import scala.slick.lifted.MappedTypeMapper
import com.typesafe.slick.driver.oracle.OracleDriver.simple._

package object model {
  def db = Database.forDataSource(DB.getDataSource())


/* Custom ID types */
  type RawID = Array[Byte]
  trait TypedId extends Any {
    def untypedId: RawID
    override def toString = untypedId.map("%02x" format _).mkString
  }
  case class AgencyId(untypedId: RawID) extends AnyVal with TypedId
  case class UserId(untypedId: RawID) extends AnyVal with TypedId


/* Custom ID type mappers */
  sealed trait IdFactory[T <: TypedId] extends (RawID => T)

  implicit object AgencyId        extends IdFactory[AgencyId]
  implicit object UserId          extends IdFactory[UserId]

  implicit def idMapper[T <: TypedId : IdFactory]: TypeMapper[T] =
    MappedTypeMapper.base[T, RawID](_.untypedId, implicitly[IdFactory[T]])


/* Tables & Queries */
  case class User(id: Option[UserId] = None,
                  name: String,
                  password: String,
                  agencyId: Option[AgencyId] = None,
                  inactive: Boolean = false,
                  disabled: Boolean = true)

  object User extends Table[User]("USER") {
    def id = column[UserId]("ID", O.PrimaryKey)
    def name = column[String]("NAME")
    def password = column[String]("PASSWORD")
    def agencyId = column[Option[AgencyId]]("AGENCY_ID")//(typeMapperToOptionTypeMapper(idMapper(AgencyId)))
    def inactive = column[Boolean]("INACTIVE", O.Default(false))
    def disabled = column[Boolean]("IS_DISABLED", O.Default(true))

    def * = id.? ~ name ~ password ~ agencyId ~ inactive ~ disabled <> (User.apply _, User.unapply _)

    def agency = foreignKey("FK_TB_USER_AGENCY_ID",agencyId,Agency)(_.id.?)
  }

  case class Agency(id: Option[AgencyId] = None, name: String, dataOutOfDate: Boolean = false)

  object Agency extends Table[Agency]("AGENCY") {
    def id = column[AgencyId]("ID", O.PrimaryKey)
    def name = column[String]("NAME")
    def dataOutOfDate = column[Boolean]("IS_DATA_OUT_OF_DATE")
    def * = id.? ~ name ~ dataOutOfDate <> (Agency.apply _, Agency.unapply _)
  }


/* Remote functions */
  val fn_hash = SimpleFunction.unary[String,String]("fn_hash")

}

我的额外Play应用程序依赖项,虽然我不认为我的问题是Play特定的:

"com.typesafe.slick" %% "slick-extensions" % "1.0.0",
"com.typesafe.play" %% "play-slick" % "0.3.3"

非常感谢提前!

1 个答案:

答案 0 :(得分:0)

显然idMapper只需要BaseTypeMapper[T]而不是TypeMapper[T]