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"
非常感谢提前!
答案 0 :(得分:0)
显然idMapper
只需要BaseTypeMapper[T]
而不是TypeMapper[T]
。