在 Scala 中使用 Slick 库获取自动增量值

Posted

技术标签:

【中文标题】在 Scala 中使用 Slick 库获取自动增量值【英文标题】:Getting autoincrement values with Slick library in Scala 【发布时间】:2012-10-18 07:58:28 【问题描述】:

如何获取使用 Slick 插入的记录的自动递增值?以下代码打印 1111。我本来希望它打印 1234

import scala.slick.driver.H2Driver.simple._

object TestMappedTable extends App
    case class User(id: Option[Int], first: String, last: String)

    object Users extends Table[User]("users") 
        def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
        def first = column[String]("first")
        def last = column[String]("last")
        def * = id.? ~ first ~ last <> (User, User.unapply _)
    

  implicit val session = Database.forURL("jdbc:h2:mem:test1", driver = "org.h2.Driver").createSession()
  session.withTransaction
    Users.ddl.create

    print(Users.insert(User(None, "Jack", "Green" )))
    print(Users.insert(User(None, "Joe", "Blue" )))
    print(Users.insert(User(None, "John", "Purple" )))
    print(Users.insert(User(None, "Jim", "Yellow" )))
  

我将 Slick 0.11.2 用于 Scala 2.10.0-RC1

【问题讨论】:

数据库是否显示1、2、3、4? @DominicBou-Samra 是的,id 是正确自动递增的。 愚蠢的问题,但是你确定Insert的返回值是id吗?我在 ScalaDoc 文档中找不到插入。有链接吗? 我还以为是这样,但事实证明我错了。感谢您的帮助。 数据操作查询通常返回受影响的行数。 【参考方案1】:

您可以像这样检索生成的值。

autoInc 方法添加到Users 对象。

def autoInc = id.? ~ first ~ last (User, User.unapply _) 返回 id

请改用Users.autoInc.insert

print(Users.autoInc.insert(User(None, "Jack", "Green" )))

另见:

https://github.com/slick/slick/issues/10

https://github.com/slick/slick/commit/09a65a8e88a0363412e218dc5c06023b69809649

【讨论】:

这对 H2 数据库很有效,但 PostgreSQL 不喜欢它。由于这不是完全相同的问题,因此我将其作为一个新问题提出:***.com/q/13199198/828757 表变大了怎么办?也许 15-20 列...forInsert 方法变成了怪物! 现在由 Slick 支持。请参阅下面的Brenden's answer。 Slick 3.0 也可以这样做。【参考方案2】:

最新版本的 Slick (2.1.0) 自动处理 ignoring the auto-incremented ids 并且文档演示了如何检索 id:

val userWithId =
  (users returning users.map(_.id)
         into ((user,id) => user.copy(id=Some(id)))
  ) += User(None, "Stefan", "Zeiger")

这是完整的 monty,检索到的值随后将插入回您要添加到表中的对象中。如果您只想掌握 id 本身:

val userId =
  (users returning users.map(_.id)) += User(None, "Stefan", "Zeiger")

两个代码 sn-ps 均取自官方文档。对于从未使用过早期版本的 Slick 的新手(比如我)来说,这个问题似乎需要更新。

【讨论】:

这是最新的答案。我不确定您是否可以“编辑”当前选择的答案以将其添加为更新或至少链接到此。 但是为什么 userId 的类型是FixedSqlAction[Int, NoStream, Effect.Write]? (在 Slick 3.0.0 中测试)如何获得 Int / Long?【参考方案3】:

根据SLICK Inserting document,你应该定义一个方法forInsert看起来像:

def forInsert = first ~ last <> (
     t =>
        User(None, t._1, t._2),
     (u: User) =>
        Some((u.first, u.last))
    ) returning id

要得到结果:

def save(user: User): User = 
    val id = users.forInsert.insert(user)
    new User(Some(id), user.first, user.last)

【讨论】:

最后一行是user.copy(id = Some(id))吗?【参考方案4】:

对我来说,以下来源有效(Slick 3.0.2)

class Track(tag: Tag)
   extends Table[(Int, String, String)](tag, "TRACK") 
   // This is the primary key column:
   def id: Rep[Int] = column[Int]("ID", O.PrimaryKey, O.AutoInc)
   def artist: Rep[String] = column[String]("ARTIST")
   def name: Rep[String] = column[String]("NAME")

   def * : ProvenShape[(Int, String, String)] =
     (id, artist, name)

【讨论】:

以上是关于在 Scala 中使用 Slick 库获取自动增量值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Play with Scala 和 Slick 从数据库中获取记录

Scala / slick:如果不存在则获取插入的行的ID

如何在 Scala Slick 中运行补丁/部分数据库更新?

浅谈Slick- 基本功能描述

Scala 用于理解 Slick Query

为不存在的表 slick scala (Slick 3.0.0, scala) 创建一个类 Table