Because that autoInc
can be confusing I will provide you a working example (please note that my DB is PostgreSQL so I need that hack with forInsert
in order to make Postgresql driver increment auto-inc values).
case class GeoLocation(id: Option[Int], latitude: Double, longitude: Double, altitude: Double)
/**
* Define table "geo_location".
*/
object GeoLocations extends RichTable[GeoLocation]("geo_location") {
def latitude = column[Double]("latitude")
def longitude = column[Double]("longitude")
def altitude = column[Double]("altitude")
def * = id.? ~ latitude ~ longitude ~ altitude <> (GeoLocation, GeoLocation.unapply _)
def forInsert = latitude ~ longitude ~ altitude <> ({ (lat, long, alt) => GeoLocation(None, lat, long, alt) },
{ g: GeoLocation => Some((g.latitude, g.longitude, g.altitude)) })
}
My RichTable is an abstract class in order to not declare ids for each Table I have but just extend this:
abstract class RichTable[T](name: String) extends Table[T](name) {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
val byId = createFinderBy(_.id)
}
and use it like:
GeoLocations.forInsert.insert(GeoLocation(None, 22.23, 25.36, 22.22))
Since you pass None
for id
, it will be generated automatically by PostgreSql driver when Slick inserts this new entity.
I have a few weeks since I started with Slick and I really recommend it!
UPDATE: If you want to not use forInsert
projections, another approach is the following - in my case the entity is Address
.
Create sequence for each table on schema creation:
session.withTransaction {
DBSchema.tables.drop
DBSchema.tables.create
// Create schemas to generate ids too.
Q.updateNA("create sequence address_seq")
}
Define a method to generate the ids using sequences (I defined this once
in RichTable
class:
def getNextId(seqName: String) = Database { implicit db: Session =>
Some((Q[Int] + "select nextval('" + seqName + "_seq') ").first)
}
and in the mapper override insert
method like:
def insert(model : Address) = Database { implicit db: Session =>
*.insert(model.copy(id = getNextId(classOf[Address].getSimpleName())))
}
And now, you can pass None
when you do an insert and this methods will do a nice work for you...