在Slick 3.0 Generic CRUD实现中键入参数绑定错误

时间:2015-09-24 12:42:41

标签: scala playframework-2.0 slick

我正在尝试为Scala播放应用程序实现通用CRUD特性。我正在关注this implementation.

这些我的依赖项 -

libraryDependencies ++= Seq(
    "org.postgresql" % "postgresql" % "9.4-1201-jdbc41",
    "com.typesafe.slick" %% "slick" % "3.0.0",
    "com.typesafe.play" %% "play-slick" % "1.0.1",
    "com.typesafe.play" %% "play-slick-evolutions" % "1.0.1",
    "io.spray" %%  "spray-json" % "1.3.2",
    specs2 % Test

这是我的通用模型 -

package models.generic

import slick.driver.PostgresDriver.api._
import scala.concurrent.Future


abstract class GenericTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
    def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
}

trait GenericCRUD[C <: GenericTable[T], T] extends configs.DBConfig{
    protected val table: TableQuery[C]

    private val queryById = Compiled((id: Rep[Int]) => table.filter(_.id === id))

    def all: Future[Seq[C#TableElementType]] = db.run(table.result)

    def create(c: C#TableElementType): Future[Int] = db.run(table += c)

    def read(id: Int): Future[Option[C#TableElementType]] = db.run(queryById(id).result.headOption)

    def update(id: Int, c: C#TableElementType): Future[Int] = db.run(queryById(id).update(c))

    def delete(id: Int): Future[Int] = db.run(queryById(id).delete)
}

这是使用泛型的模型实现 -

package models

import java.sql.Timestamp
import scala.concurrent.Future
import slick.driver.PostgresDriver.api._
import generic.{GenericCRUD, GenericTable}


case class Brand(id: Int, name: String, created: Timestamp, updated: Timestamp)

class BrandTable(tag: Tag) extends GenericTable[Brand](tag, "brand") {
    override def id = column[Int]("id", O.PrimaryKey, O.AutoInc)

    def name = column[String]("name")

    def created = column[Timestamp]("created")

    def updated = column[Timestamp]("updated")

    def * = (id, name, created, updated) <>((Brand.apply _).tupled, Brand.unapply)
}

object Brands extends GenericCRUD[Brand, BrandTable] {

    override val table:TableQuery[Brand] = TableQuery[Brand]

}

目前我收到以下错误 -

play.sbt.PlayExceptions$CompilationException: Compilation error[type arguments [models.Brand] conform to the bounds of none of the overloaded alternatives of
 value apply: [E <: slick.lifted.AbstractTable[_]]=> slick.lifted.TableQuery[E] <and> [E <: slick.lifted.AbstractTable[_]](cons: slick.lifted.Tag => E)slick.lifted.TableQuery[E]]
        at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27) ~[na:na]
        at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27) ~[na:na]
        at scala.Option.map(Option.scala:145) ~[scala-library-2.11.7.jar:na]
        at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:49) ~[na:na]
        at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:44) ~[na:na]
        at scala.Option.map(Option.scala:145) ~[scala-library-2.11.7.jar:na]
        at play.sbt.run.PlayReload$.taskFailureHandler(PlayReload.scala:44) ~[na:na]
        at play.sbt.run.PlayReload$.compileFailure(PlayReload.scala:40) ~[na:na]
        at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17) ~[na:na]
        at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17) ~[na:na]
        at scala.util.Either$LeftProjection.map(Either.scala:377) ~[scala-library-2.11.7.jar:na]
        at play.sbt.run.PlayReload$.compile(PlayReload.scala:17) ~[na:na]
        at play.sbt.run.PlayRun$$anonfun$playRunTask$1$$anonfun$apply$2$$anonfun$apply$3$$anonfun$2.apply(PlayRun.scala:61) ~[na:na]
        at play.sbt.run.PlayRun$$anonfun$playRunTask$1$$anonfun$apply$2$$anonfun$apply$3$$anonfun$2.apply(PlayRun.scala:61) ~[na:na]
        at play.runsupport.Reloader$$anonfun$reload$1.apply(Reloader.scala:323) ~[na:na]
        at play.runsupport.Reloader$$anon$3.run(Reloader.scala:43) ~[na:na]
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_51]
        at play.runsupport.Reloader$.play$runsupport$Reloader$$withReloaderContextClassLoader(Reloader.scala:39) ~[na:na]
        at play.runsupport.Reloader.reload(Reloader.scala:321) ~[na:na]
        at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:113) ~[play-server_2.11-2.4.3.jar:2.4.3]
        at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:111) ~[play-server_2.11-2.4.3.jar:2.4.3]
        at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) ~[scala-library-2.11.7.jar:na]
        at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) ~[scala-library-2.11.7.jar:na]
        at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40) ~[akka-actor_2.11-2.3.13.jar:na]
        at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397) ~[akka-actor_2.11-2.3.13.jar:na]
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) ~[scala-library-2.11.7.jar:na]
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) ~[scala-library-2.11.7.jar:na]
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) ~[scala-library-2.11.7.jar:na]
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) ~[scala-library-2.11.7.jar:na]

2 个答案:

答案 0 :(得分:2)

我发现了错误。我在GenericCRUD特征中交换了泛型类型的位置。这是更正后的版本 -

通用模型:

package models

import java.sql.Timestamp
import scala.concurrent.Future
import slick.driver.PostgresDriver.api._
import generic.{GenericCRUD, GenericTable}


case class Brand(id: Int, name: String, created: Timestamp, updated: Timestamp)

class BrandTable(tag: Tag) extends GenericTable[Brand](tag, "brand") {
    override def id = column[Int]("id", O.PrimaryKey, O.AutoInc)

    def name = column[String]("name")

    def created = column[Timestamp]("created")

    def updated = column[Timestamp]("updated")

    def * = (id, name, created, updated) <>((Brand.apply _).tupled, Brand.unapply)
}

object Brands extends GenericCRUD[BrandTable, Brand] {
    override val table = TableQuery[BrandTable]
}

已实施模型:

package models.generic

import slick.driver.PostgresDriver.api._
import scala.concurrent.Future


abstract class GenericTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
    def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
}

trait GenericCRUD[C <: GenericTable[T], T] extends configs.DBConfig{
    protected val table: TableQuery[C]

    private val queryById = Compiled((id: Rep[Int]) => table.filter(_.id === id))

    def all: Future[Seq[C#TableElementType]] = db.run(table.result)

    def create(c: C#TableElementType): Future[Int] = db.run(table += c)

    def read(id: Int): Future[Option[C#TableElementType]] = db.run(queryById(id).result.headOption)

    def update(id: Int, c: C#TableElementType): Future[Int] = db.run(queryById(id).update(c))

    def delete(id: Int): Future[Int] = db.run(queryById(id).delete)
}

答案 1 :(得分:1)

我正在使用这个CRUD实现:

https://github.com/jose78/Dashboard-DB/blob/master/src/main/scala/com/github/elx/dashboard/db/TableConf.scala

LOAD DATA
INFILE  'C:\Users\Appdata\Desktop\SQl Loader\ing1.txt'
BADFILE 'C:\Users\Appdata\Desktop\SQl Loader\bad_orders.txt'
INTO TABLE Ing_Details 
FIELDS
TERMINATED BY "\t"
OPTIONALLY ENCLOSED BY '"' 
     TRAILING NULLCOLS
( 
INGREDIENT_ID NULLIF INGREDIENT_TYPE_ID=BLANKS,
INGREDIENT_TYPE_ID NULLIF INGREDIENT_TYPE_ID=BLANKS,
Status NULLIF Status=BLANKS,
Organic NULLIF Organic=BLANKS
)

我希望你喜欢它。