0

对于 scala 项目,我同时使用play-slick两个play-slick-evolutions版本,并使用version5.0.0生成我的数据库类。slick-codegen3.3.3

我有一个带有一primary key列的表和一些带有default values. 我想插入一行而不提及主键列或任何具有默认值的列。理想情况下,此操作应返回已创建行的新主键。

我的问题是生成的代码slick-codegen似乎只允许插入完整的行,因为它对行使用自己的案例类。这是生成的代码的样子(没有注释):

case class SalesOrderRow(idSalesOrder: Int, fkCustomer: Int, createdAt: java.sql.Timestamp, createdBy: Option[String] = None)

implicit def GetResultSalesOrderRow(implicit e0: GR[Int], e1: GR[java.sql.Timestamp], e2: GR[Option[String]]): GR[SalesOrderRow] = GR{
  prs => import prs._
  SalesOrderRow.tupled((<<[Int], <<[Int], <<[java.sql.Timestamp], <<?[String]))
}

class SalesOrder(_tableTag: Tag) extends profile.api.Table[SalesOrderRow](_tableTag, Some("test"), "sales_order") {
  def * = (idSalesOrder, fkCustomer, createdAt, createdBy) <> (SalesOrderRow.tupled, SalesOrderRow.unapply)
  def ? = ((Rep.Some(idSalesOrder), Rep.Some(fkCustomer), Rep.Some(createdAt), createdBy)).shaped.<>({r=>import r._; _1.map(_=> SalesOrderRow.tupled((_1.get, _2.get, _3.get, _4)))}, (_:Any) =>  throw new Exception("Inserting into ? projection not supported."))

  val idSalesOrder: Rep[Int] = column[Int]("id_sales_order", O.AutoInc, O.PrimaryKey)
  val fkCustomer: Rep[Int] = column[Int]("fk_customer")
  val createdAt: Rep[java.sql.Timestamp] = column[java.sql.Timestamp]("created_at")
  val createdBy: Rep[Option[String]] = column[Option[String]]("created_by", O.Length(20,varying=true), O.Default(None))
}

lazy val SalesOrder = new TableQuery(tag => new SalesOrder(tag))

有了这个生成的代码,我现在可以插入一行并提到整列:

val insertActionsNotSoNice =
  DBIO.seq(
    salesOrders += Tables.SalesOrderRow(0, 3, new Timestamp(System.currentTimeMillis()), Some("这个不好"))
  )

但是我想省略开头的主键和具有默认值的时间戳参数。但是不能做这样的事情。

val insertActionsNotCompiling =
  DBIO.seq(
    salesOrders.map(so => (so.fkCustomer, so.createdBy) += (3, Some("这个好&quot;)))
  )

我在 slick 文档和 Web 中发现了许多类似后一种方法的示例,但它们用于数据库的类确实有一个元组而不是自己的行类。喜欢...

class Coffees(tag: Tag) extends Table[(String, Int, Double, Int, Int)](tag, "COFFEES")

代替

class Coffees(_tableTag: Tag) extends profile.api.Table[CoffeesRow](_tableTag, Some("test"), "coffee")

我是否必须slick-codegen放弃我的项目并自己编写所有类以满足我的需求,还是我的库组合有play-slick误?或者在插入未记录的内容时是否有一个简单的技巧来省略列?

4

1 回答 1

1

经过几天的尝试,我找到了一个解决方案。

您可以映射查询以仅选择要插入的列,然后在returning要返回插入行的 id 时使用。

import dao.Tables.profile.api._

// ...

val salesOrders = TableQuery[SalesOrder]
val insertStatement = salesOrders.map(so => (so.fkCustomer, so.createdBy)) returning salesOrders.map(_.idSalesOrder) into ((_, id) => id)

然后你可以写这样的东西:

val newSalesOrderIdFuture = db.run(insertStatement += (5, Some("有效")))

所以我在我的插入语句中省略了主键列 ( ) 和数据库id_sales_order中默认的时间戳列( )。now()created_at

于 2021-03-21T10:49:42.283 回答