下面的代码有效,但我不禁想到我正在做一些不合适的asInstanceOf[B]
演员。
基本上,在传递某种类型的TableQuery
之后,我希望mapper
变成一个动作,然后根据一个函数将map
变成一个DAO列表传递给它。
我坚持的是函数的类型,或者可能是如何公开TableQuery类型的内部类型。我想做一些像[B <: TableElementType]
f: B => A
这样的事情,而不是对B的可能残酷演员。
我想我认为我知道我将在下面的示例中获得类似AgencyRow
的内容以映射到AgencyDAO,我如何在方法的类型签名中捕获它?
的映射
def mapper[A <: BaseDAO, B <: DatabaseAccessObject, T <: TableQuery[E], E <: AbstractTable[_]](query: T, f: B => A) : Seq[A] = {
val result = exec(query.result)
result.map(o => f(o.asInstanceOf[B]))
}
def exec[T](action: DBIO[T]): T = Await.result(db.run(action), 4 seconds)
使用Mapper(测试代码)
val list = mapper[AgencyDAO, AgencyRow, TableQuery[Agency], Agency](agencies, AgencyDAODomainObject.convertFromRow)
list.length should equal(75)
Slick Schema
case class AgencyRow(id: Int, name: Option[String] = None) extends DatabaseAccessObject
class Agency(_tableTag: Tag) extends Table[AgencyRow](_tableTag, "agency") {
def * = (id, name) <>(AgencyRow.tupled, AgencyRow.unapply)
def ? = (Rep.Some(id), name).shaped.<>({ r => import r._; _1.map(_ => AgencyRow.tupled((_1.get, _2))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))
val id: Rep[Int] = column[Int]("id", O.AutoInc, O.PrimaryKey)
val name: Rep[Option[String]] = column[Option[String]]("name", O.Length(200, varying = true), O.Default(None))
}
lazy val Agency = new TableQuery(tag => new Agency(tag))enter code here
DAO Mapper
package object Implicits {
implicit class DomainObjectOps[A <: BaseDAO](a: A)(implicit ev: DomainObject[A]) {
def name = ev.name(a)
def id = ev.id(a)
}
}
trait BaseDAO
trait DomainObject[A <: BaseDAO] {
def id(a: A): Int
def name(a: A): String
}
case class AgencyDAO(val id: Int, val name: String) extends BaseDAO
object AgencyDAO {
implicit object AgencyDAODomainObject extends DomainObject[AgencyDAO] {
def convertToRow(o: AgencyDAO) = AgencyRow(o.id, Some(o.name))
def convertFromRow(o: AgencyRow) = AgencyDAO(o.id, o.name.getOrElse(""))
override def id(a: AgencyDAO) = a.id
override def name(a: AgencyDAO) = a.name
}
}
答案 0 :(得分:0)
如果其他人可能会发现这个相关或有启发性:而不是在映射器内的查询上调用result
,而是传入已调用的result
,返回{{1} }。 Slick有一个方便的别名DBIOAction[R]
,可以要求DBIO[R]
扩展R
,无需播放。所以现在:
Seq[B]
def resultMapper[A <: BaseDAO, B <: DatabaseAccessObject, S <: DBIO[Seq[B]]](action: S)(implicit rowMapper: B => A) : Seq[A] = {
val result = exec(action)
result.map(rowMapper)
}