简体   繁体   English

Scala:需要类类型,但在特征中找到{泛型类型}

[英]Scala: class type required but {generic type} found in trait

I'm using Slick 3.0 and trying to create a trait to offer basic operations. 我正在使用Slick 3.0并尝试创建一个特性来提供基本操作。 Here is my trait: 这是我的特点:

object DAO {
  var db: Database = null
}

trait CommonAPI[T <: Table[_]] {
  private val db = DAO.db
  private val objects = TableQuery[T]

  def count: Future[Int] = db.run(objects.length.result)
  def insert(obj: T#TableElementType): Future[Int] = db.run(objects += obj)
  def all: Future[Seq[T]] = db.run(objects.result)
}

DAO.db is initialized in Play's onStart method. DAO.db在Play的onStart方法中初始化。 However, I met compilation error class type required but T found in line private val objects = TableQuery[T] . 但是,我遇到了class type required but T found编译错误class type required but T found在行private val objects = TableQuery[T] class type required but T foundclass type required but T found private val objects = TableQuery[T]

What am I supposed to do? 我应该做些什么? Thanks! 谢谢!

Here is one solution: 这是一个解决方案:

At first, define this to avoid class type issue.. 首先,定义它以避免类类型问题..

class Service[T <: Table[_]](path: String, cons: Tag => T){

  lazy val db = Database.forConfig(path)

  def query = TableQuery[T](cons)
}

Then use it this way, Post is sub class of Table: 然后以这种方式使用它,Post是表的子类:

object Abcd {

  object Def extends Service[Post]("mydb", abc) {



    def test = {


      //db

      val q = query.drop(1).take(20)
      val r = db.run(q.result)

      println(q.result.statements.head)
      println(r)

      r

    }
  }

  private def abc(tag: Tag) = new Post(tag)

}

This solution tested ok. 此解决方案测试正常。

Hi I have done something similar. 嗨,我做了类似的事情。 I used a bit different approach. 我用了一点不同的方法。 I have one generic DAO and few(per resource/table) classes which just inherits for it. 我有一个通用的DAO和很少(每个资源/表)类只是为它继承。

this is generic DAO: 这是通用的DAO:

class BaseDbEntity[T <: BaseEntity, R <: BaseT[T]](val tableName: String, tableQuery: TableQuery[R]) extends DatabaseAccess{

  val createReturningId = tableQuery returning tableQuery.map{item => item.id}

  def create(entity: T): Int = {
    connectionPool withSession {
      implicit session =>
        val resId = createReturningId += entity
        resId
    }
  }

  def getAll = {
    connectionPool withSession {
      implicit session =>
        tableQuery.list
    }
  }
}

code of full class: ( https://github.com/vixxx123/scalasprayslickexample/blob/master/src/main/scala/com/vixxx123/scalasprayslickexample/database/BaseDbEntity.scala ) 全班代码:( https://github.com/vixxx123/scalasprayslickexample/blob/master/src/main/scala/com/vixxx123/scalasprayslickexample/database/BaseDbEntity.scala

and Specific DAO with corresponding Table class: 和具有相应表类的特定DAO:

class PersonDao extends BaseDbEntity[Person, PersonT]("person", TableQuery[PersonT])

class PersonT(tag: Tag) extends BaseT[Person](tag, "person") {
  def name: Column[String] = column[String]("name")
  def lastname: Column[String] = column[String]("lastname")

  override def * = (id.?, name, lastname) <> (
    (Person.apply _).tupled, Person.unapply)
}

you can find that class here: https://github.com/vixxx123/scalasprayslickexample/blob/master/src/main/scala/com/vixxx123/scalasprayslickexample/exampleapi/person/PersonDao.scala 你可以在这里找到这个课程: https//github.com/vixxx123/scalasprayslickexample/blob/master/src/main/scala/com/vixxx123/scalasprayslickexample/exampleapi/person/PersonDao.scala

Maybe it will help you out. 也许它会帮助你。

You can pass a tag instead and create table query from it , if your table class is defined as : 如果您的表类定义为:您可以传递标记,并从中创建表查询:

case class Sample(....)

class SampleTable(tag: Tag)
  extends Table[Sample](tag, "sample_table") {
    .....
}

then you can implement your generic trait as below : 然后你可以实现你的通用特征如下:

import scala.slick.driver.MySQLDriver.simple.Tag // here mysql is used , you can import the driver specific to your db

object DAO {
  var db: Database = null
}

trait CommonAPI[T, A<: Table[T]] {
  private val db = DAO.db
  private val tableTag : Tag => A = _
  def setTag(tag : Tag => A) = { tableTag = tag }
  private val objects = TableQuery(tableTag)

  def count: Future[Int] = db.run(objects.length.result)
  def insert(obj: T#TableElementType): Future[Int] = db.run(objects += obj)
  def all: Future[Seq[T]] = db.run(objects.result)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM