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

I am using Slick 3.0 and am trying to create a tag to suggest basic operations. Here's 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

initialized in the play method onStart

. However, I came across a compilation error class type required but T found

on the line private val objects = TableQuery[T]

.

What should I do? Thank!

+3


source to share


3 answers


Here's one solution:

Define this first to avoid the class type problem.

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 a subclass of the class:

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 has been tested ok.

+2


source


Hi I did something similar. I took a slightly different approach. I have one generic DAO and several (per resource / table) classes that are just inherited for it.

this is a generic 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
    }
  }
}

      

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



and a concrete DAO with a matching Table class:

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 this class here: https://github.com/vixxx123/scalasprayslickexample/blob/master/src/main/scala/com/vixxx123/scalasprayslickexample/exampleapi/person/PersonDao.scala

Maybe this will help you.

0


source


Instead, you can pass in a tag and create a 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 like 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)
}

      

0


source







All Articles