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!
source to share
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.
source to share
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.
source to share
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)
}
source to share