如何在Slick中显式指定AutoInc列的值

时间:2017-02-16 21:22:25

标签: scala slick slick-3.0

默认情况下,Slick忽略带有O.AutoInc标志的列中的值,并允许数据库在插入操作期间填充该值。

但有时我需要为自动递增列插入一些特定值,而Slick仍然会忽略它。有没有办法做到这一点?

我知道,我可以制作第二个表定义,没有O.AutoInc标志,但我正在寻找更优雅的方法来做到这一点。

更新: 这是我的案例类和表定义:

case class Transaction (id: Long, timestamp: LocalDateTime, comment: Option[String])
class Transactions(tag: Tag) extends Table[Transaction](tag, "tx") {
  implicit val localDTtoDate = MappedColumnType.base[LocalDateTime, Timestamp] (
    l => Timestamp.valueOf(l),
    d => d.toLocalDateTime
  )

  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def timestamp = column[LocalDateTime]("ts")
  def comment = column[Option[String]]("comment")
  def * = (id, timestamp, comment) <> ((Transaction.apply _).tupled, Transaction.unapply)
}

2 个答案:

答案 0 :(得分:0)

如果您将id字段标记为Option al,则应该可以轻微调整*投影进行插入:

case class Transaction (id: Option[Long], timestamp: LocalDateTime,
  comment: Option[String])
class Transactions(tag: Tag) extends Table[Transaction](tag, "tx") {
  // Use the ? method on your id column to map it to an option.
  def * = (id.?, timestamp, comment) <> (
    (Transaction.apply _).tupled, Transaction.unapply)
}

这样,使用id=None插入的行将生成新的id,而id=Some(value)的行将设置为id=value。要回读插入的ID,请使用returning ... into

// `tx` is a Transaction instance, `transactions` is a
// TableQuery[Transactions] instance.
(transactions.returning(transactions.map(_.id)).into { (_, id) =>
  tx.copy(id = id)
}) += tx

答案 1 :(得分:0)

我在遇到一个非常类似的问题时发现了这个问题。 遗憾的是,我们无法使建议的解决方案发挥作用。

我们决定让O.AutoInc去,但保持列的序列和默认值为该序列的nextval

  Column  |  Type  |                 Modifiers
----------+--------+----------------------------------------------
 id       | bigint | not null default nextval('id_seq'::regclass)

然后我们只是在插入时省略了需要自动生成的id。

链接到文档的相关部分: http://slick.lightbend.com/doc/3.1.0/queries.html#inserting

在这种情况下,它看起来像这样:

if (you have an explicit id) transactions += tx
else transactions.map(t => (t.timestamp, t.comment)) += (tx.timestamp, tx.comment)