Scala Slick - Вставить в таблицу с опусканием некоторых столбцов и возвратом первичного ключа новой строки

Для проекта scala я использую с play-slick-evolutions обе версии 5.0.0 и я создаю свои классы db с версией 3.3.3.

У меня есть стол с primary key столбец и несколько столбцов с default values. Я хочу вставить одну строку, не упоминая ни столбец первичного ключа, ни какие-либо столбцы со значениями по умолчанию. В идеале это действие должно возвращать новый первичный ключ созданной строки.

Моя проблема в том, что сгенерированный код, кажется, позволяет вставлять только полные строки, потому что он использует собственный класс case для строк. Вот так выглядит сгенерированный код (без комментариев):

      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("这个好")))
  )

Я нашел много примеров с чем-то вроде последнего подхода в красивой документации и в Интернете, но всегда было так, что их классы, используемые для базы данных, имели кортеж вместо собственного класса строки. Нравиться...

      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неправильный? Или есть простой способ опустить столбцы при вставке того, что не задокументировано?

1 ответ

Решение

После нескольких дней пробования нескольких вещей я нашел одно решение.

Вы можете сопоставить запрос, чтобы выбрать только те столбцы, которые хотите вставить, а затем использовать returning если вы хотите вернуть идентификатор вставленной строки.

      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) в моем операторе вставки.

Другие вопросы по тегам