2

I am using slick 2.0.1 (and can upgrade if required) and I want to retrieve the auto incrementing value from the database (postgresql).

I have seen a few questions on SO on this already, but they are fairly old and I was hoping there was a better way than to do what this answer suggests: Scala & Play! & Slick & PostgreSQL auto increment

def autoInc = name ~ price ~ description returning id

def add(product: Product)(implicit s:Session): Long = {
    Products.autoInc.insert(p.name, p.price, p.description)
}

You have to re-enter the model's fields in the autoInc method, which is duplicating things which I am hoping to avoid.

Is there a better way or I should just do it like this?

The way I have chosen is to have my models poso (plain old scala objects like):

case class Product(.....)

And then my dao class looks like:

class ProductDao extends ProductDao {
  class Products(tag: Tag) extends Table[Product](tag, "products") {

     def id = ...
     def name = ..

     def * = (id, name) <> (Product.tupled, Product.unapply)

  }

  val products = TableQuery()
}

Also as a side note, for the * method do I have to enter all the properties like that or is there a better way for that also?

Community
  • 1
  • 1
Blankman
  • 259,732
  • 324
  • 769
  • 1,199

1 Answers1

5

The autoInc or forInsert projection pattern you have seen applies to Slick 1 but not Slick 2, where auto incremented values are automatically ignored in inserts. See http://slick.typesafe.com/doc/2.0.2/migration.html#inserting

Can you better than repeating your column names? Or multiple manifestations of artifacts of your data model for that matter? Code generation is one way to do it: http://slick.typesafe.com/doc/2.0.2/code-generation.html I will be speaking about this at Scala days.

For returning the id use returning just like in Slick 1. http://slick.typesafe.com/doc/2.0.2/queries.html#inserting

cvogt
  • 11,260
  • 30
  • 46
  • I see, but how do I get the auto incremented value back when I insert? – Blankman May 29 '14 at 02:44
  • I understand that part, I want to know the slick 2 way of returning the primary key/auto incremented value from the database when I insert a new row. – Blankman May 29 '14 at 02:46
  • `returning` just like in Slick 1. http://slick.typesafe.com/doc/2.0.2/queries.html#inserting – cvogt May 29 '14 at 03:25
  • Thanks. Previously I was inserting my model with this very clear and explicit statement: ```users.insert(user)``` Now I am inserting like this so I can get the PK autoinc id back, can you explain this statement so we know what is happening b/c it seems very magical to me: ```val newId = (users returning users.map(_.id) += user``` Where is the insert statement, I understand that returning is fetching the db id value, but I see no insert call. thanks! – Blankman May 29 '14 at 10:35
  • also does it make sense to return Option[Int] or should I just return an Int b/c an exception is thrown if the insert fails? – Blankman May 29 '14 at 10:38
  • users is a query representing the while table in your case. `returning` converts it to an invoker (a Slick thing), that allows inserts returning keys. We still support `.insert` in Slick 2, but we generally try to stick to existing Scala syntax. The Scala syntax for inserting something into a mutable collection is `+=`, so we added that as an alternative to insert. – cvogt May 29 '14 at 10:46
  • regarding the Option... doesn't matter. – cvogt May 29 '14 at 10:47
  • I see, so when you add to the mutable collection, it automatically performs the insert right away. That is what confused me, I am used to calling "insert" as seems to give me control when the call will actually execute. thanks. – Blankman May 29 '14 at 10:55
  • 1
    I don't know what you mean. `+=` is just an alias for `insert`. Same behavior. – cvogt May 30 '14 at 04:26