I've been looking around on how to implement a generic trait for commons CRUD and other kinds of operations, I looked at this and this and the method specified are working well.
What I would like to have is a generic method for insertion, my class looks like this at the moment (non generic implementation):
object CampaignModel {
val campaigns = TableQuery[Campaign]
def insert(campaign: CampaignRow)(implicit s: Session) = {
campaigns.insert(campaign)
}
}
What I tried so far, following the first link, was this (generic implementation):
trait PostgresGeneric[T <: Table[A], A] {
val tableReference = TableQuery[T]
def insertGeneric(row: ? What type goes here ?)(implicit s: Session) = tableReference.insert(row)
}
When I inspect the insert
method it looks like the right type should be T#TableElementType
but my knowledge is pretty basic and I can't wrap my head around types, I tried T
and A
and the compiler says that the classtype does not conform to the trait one's.
Other infos, the tables are generated with the slick table generation tools
case class CampaignRow(id: Long, name: Option[String])
/** Table description of table campaign. Objects of this class serve as prototypes for rows in queries. */
class Campaign(tag: Tag) extends Table[CampaignRow](tag, "campaign") {
def * = (id, name) <>(CampaignRow.tupled, CampaignRow.unapply)
/** Maps whole row to an option. Useful for outer joins. */
def ? = (id.?, name).shaped.<>({
r => import r._; _1.map(_ => CampaignRow.tupled((_1.get, _2)))
}, (_: Any) => throw new Exception("Inserting into ? projection not supported."))
/** Database column id AutoInc, PrimaryKey */
val id: Column[Long] = column[Long]("id", O.AutoInc, O.PrimaryKey)
/** Database column name */
val name: Column[Option[String]] = column[Option[String]]("name")
}
I managed to make it work, this is my generic trait:
Where
RichTable
is an abstract class with an id field, this, with the upper bound constraint is useful to get the id field ofT#TableElementType
(see this for more info):And my campaign table now looks like this:
The model implementing the generic trait looks like this: