scalaplayframeworkslickplayframework-evolutions

Insert row with auto increment id - Playframework Scala - Slick


One of my evolution contains a very simple table definition with BIGSERIAL column:

CREATE TABLE product (
  id    BIGSERIAL NOT NULL PRIMARY KEY,
  name  VARCHAR   NOT NULL,
  color VARCHAR   NOT NULL
);

I use SlickCodeGenerator to generate classes from the database itself:

case class ProductRow(id: Long, name: String, color: String)

implicit def GetResultProductRow(implicit e0: GR[Long], e1: GR[String]): GR[ProductRow] = GR{
    prs => import prs._
    ProductRow.tupled((<<[Long], <<[String], <<[String]))
}

class Product(_tableTag: Tag) extends Table[ProductRow](_tableTag, "product") {
  def * = (id, name, color) <> (ProductRow.tupled, ProductRow.unapply)
  def ? = (Rep.Some(id), Rep.Some(name), Rep.Some(color)).shaped.<>({r=>import r._; _1.map(_=> ProductRow.tupled((_1.get, _2.get, _3.get)))}, (_:Any) =>  throw new Exception("Inserting into ? projection not supported."))

  val id: Rep[Long] = column[Long]("id", O.AutoInc, O.PrimaryKey)
  val name: Rep[String] = column[String]("name")
  val color: Rep[String] = column[String]("color")
}

lazy val Product = new TableQuery(tag => new Product(tag))

I would like to insert a row to Product table without an id so it would be generated by database. The problem is ProductRow.id is not optional. Most of the solutions suggest adding new methods to Product class, however I must not touch sources generated by slick as the changes could be lost any time. Is there a way to insert the row without an ID using such generated files?

I use Slick 3.0, Playframework 2.4.1.

Edit: Sending dummy id solves the issue, however it is redundant over the wire. I am looking for something like: insert into product(name, color) values('name', 'color').


Solution

  • you can send any value as id in productRow, if its bigserial...it should be replaced by the autogenerated value...and even if you dont want to send id then create one case class without id having same fields as product to send :

    case class ProductSimilar(name: String, color: String)
    val prodSimilar =ProductSimilar("name","color")
    

    before inserting copy the fields except the id field and you can insert to database :

     val db: PostgresDriver.backend.DatabaseDef = Database.forURL(url, user=user, password=password, driver= jdbcDriver)
        val row = Product(0L ,prodSimilar.name,prodSimilar.color)
        db.run(query returning query.map(obj => obj) += row)
    

    Hope this is helpful...