4

我试图了解 Slick 的工作原理以及如何使用它......并查看他们在 GitHub 中的示例,我最终在MultiDBCakeExample.scala中得到了这个代码片段:

trait PictureComponent { this: Profile => //requires a Profile to be mixed in...
  import profile.simple._ //...to be able import profile.simple._

  object Pictures extends Table[(String, Option[Int])]("PICTURES") {
    ...

    def * = url ~ id

    val autoInc = url returning id into { case (url, id) => Picture(url, id) }

    def insert(picture: Picture)(implicit session: Session): Picture = {
      autoInc.insert(picture.url)
    }
  }
}

我想该*方法返回表中的一行,而autoInc应该以某种方式提供自动递增实体 ID 的功能......但老实说,我在理解这段代码时遇到了一些麻烦。returning指的是什么?返回什么autoInc

我查看了 Slick 文档,但找不到有用的信息。任何帮助将非常感激 ;-)

4

1 回答 1

6

因为这autoInc可能会令人困惑,所以我将为您提供一个工作示例(请注意,我的数据库是 PostgreSQL,所以我需要使用该 hackforInsert来使 Postgresql 驱动程序增加 auto-inc 值)。

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)) })
}

我的 RichTable 是一个抽象类,以便不为我拥有的每个表声明 id,而只是扩展它:

abstract class RichTable[T](name: String) extends Table[T](name) {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)

  val byId = createFinderBy(_.id)

}

并像这样使用它:

GeoLocations.forInsert.insert(GeoLocation(None, 22.23, 25.36, 22.22))

因为你传递None了 for id,所以当 Slick 插入这个新实体时,它将由 PostgreSql 驱动程序自动生成。自从我开始使用 Slick 以来,我已经有几个星期了,我真的推荐它!

更新:如果您不想使用forInsert投影,另一种方法是以下 - 在我的情况下,实体是Address.

在创建模式时为每个表创建序列:

session.withTransaction {
  DBSchema.tables.drop
  DBSchema.tables.create
  // Create schemas to generate ids too.
  Q.updateNA("create sequence address_seq")
}

定义一个使用序列生成 id 的方法(我onceRichTable类中定义了这个:

  def getNextId(seqName: String) = Database { implicit db: Session =>
    Some((Q[Int] + "select nextval('" + seqName + "_seq') ").first)
  }

并在映射器覆盖insert方法中,如:

  def insert(model : Address) = Database { implicit db: Session =>
    *.insert(model.copy(id = getNextId(classOf[Address].getSimpleName())))
  }

现在,您可以None在进行插入时通过,并且此方法将为您做得很好...

于 2012-12-06T11:18:23.490 回答