Slick 2.0 Common CRUD Operations

I looked around how to implement a common feature for commons CRUD and other kinds of operations, I looked at this and this and the specified method works well.

What I would like to have is a generic method to insert, my class currently looks like (not a generic implementation):

object CampaignModel { val campaigns = TableQuery[Campaign] def insert(campaign: CampaignRow)(implicit s: Session) = { campaigns.insert(campaign) } } 

What I tried so far, from the first link, was this (general 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 test the insert method, it looks like the correct type should be T#TableElementType , but my knowledge is pretty simple and I can’t wrap my head around the types, I tried T and A , and the compiler says that classtype does not match the attribute .

Other information, tables are generated using the tools for generating slice

 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") } 
+6
source share
1 answer

I managed to get it working, this is my common trait:

 import scala.slick.driver.PostgresDriver import scala.slick.driver.PostgresDriver.simple._ import path.to.RichTable trait PostgresGeneric[T <: RichTable[A], A] { val tableReference: TableQuery[T] def insert(row: T#TableElementType)(implicit s: Session) = tableReference.insert(row) def insertAndGetId(row: T#TableElementType)(implicit s: Session) = (tableReference returning tableReference.map(_.id)) += row def deleteById(id: Long)(implicit s: Session): Boolean = tableReference.filter(_.id === id).delete == 1 def updateById(id: Long, row: T#TableElementType)(implicit s: Session): Boolean = tableReference.filter(_.id === id).update(row) == 1 def selectById(id: Long)(implicit s: Session): Option[T#TableElementType] = tableReference.filter(_.id === id).firstOption def existsById(id: Long)(implicit s: Session): Boolean = { (for { row <- tableReference if row.id === id } yield row).firstOption.isDefined } } 

Where RichTable is an abstract class with an id field, this, with a restriction above, is useful for getting the id field of T#TableElementType (see this for more information):

 import scala.slick.driver.PostgresDriver.simple._ import scala.slick.jdbc.{GetResult => GR} abstract class RichTable[T](tag: Tag, name: String) extends Table[T](tag, name) { val id: Column[Long] = column[Long]("id", O.PrimaryKey, O.AutoInc) } 

And my campaign table now looks like this:

 import scala.slick.driver.PostgresDriver.simple._ import scala.slick.jdbc.{GetResult => GR} import scala.slick.lifted.TableQuery case class CampaignRow(id: Long, name: Option[String]) class Campaign(tag: Tag) extends RichTable[CampaignRow](tag, "campaign") { def * = (id, name) <>(CampaignRow.tupled, CampaignRow.unapply) def ? = (id.?, name).shaped.<>({ r => import r._; _1.map(_ => CampaignRow.tupled((_1.get, _2))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported.")) override val id: Column[Long] = column[Long]("id", O.AutoInc, O.PrimaryKey) val name: Column[Option[String]] = column[Option[String]]("name") } 

A model that implements a common feature is as follows:

  object CampaignModel extends PostgresGeneric[Campaign, CampaignRow] { override val tableReference: PostgresDriver.simple.TableQuery[Tables.Campaign] = TableQuery[Campaign] def insertCampaign(row: CampaignRow) = { insert(CampaignRow(0, "test")) } } 
+11
source

All Articles