Anorm Scala 插入带有嵌套列表的对象列表

Anorm Scala insert list of objects with nested list

我发现自己需要将具有嵌套元素序列的元素序列插入到 PostgreSQL 数据库中,最好使用单个语句,因为我要返回 Future。我正在使用 Scala Play 和 Anorm。

我的数据如下所示。

case class Question(id: Long, titel: String)
case class Answer(questionId: Long, text: String)

在数据库中它看起来像这样:

CREATE TABLE questions (
  question_id SERIAL PRIMARY KEY NOT NULL,
  titel TEXT NOT NULL,
);

CREATE TABLE answers (
  answer_id SERIAL PRIMARY KEY NOT NULL,
  question_id INT NOT NULL,
  text TEXT NOT NULL,
  FOREIGN KEY (question_id) REFERENCES questions(question_id) ON DELETE CASCADE
);

我的函数看起来像这样:

def saveFormQuestions(questions: Seq[Question], answers: Seq[Answer]): Future[Long] = {
  Future {
    db.withConnection{ implicit c =>
      SQL(
        // sql
      ).executeInsert()
    }
  }
}

不知何故,在 Anorm 中,SQL 或两者,我必须执行以下操作,最好是在单个事务中:

我是 Scala Play 的新手,所以我可能做了一些不该做的假设。任何让我入门的想法都将不胜感激。

正如其名称所示,Anorm 不是 ORM,不会为您生成语句。

您必须确定适合表示数据和关系的语句(例如 my Acolyte tutorial)。

至于事务,Anorm 是 JDBC 的 thin/smart 包装器,因此 JDBC 事务语义是保留的。顺便说一句,Play 在其 DB 分辨率实用程序中提供了 .withTransaction

我用 db.withConnection 块中的逻辑解决了它。不知何故,我假设你必须在 db.withConnection 中有一个 SQL 语句,结果证明不是这样。所以像这样:

val idMap = scala.collection.mutable.Map[Long,Long]() // structure to hold map of old ids to new
db.withConnection { implicit conn =>
  // save all questions and gather map of the new ids to the old
  for (q <- questions) {
    val id: Long = SQL("INSERT INTO questions (titel) VALUES ({titel})")
      .on('titel -> q.titel)
      .executeInsert(scalar[Long].single)
    idMap(q.id) = id
  }

  // save answers with new question ids
  if (answers.nonEmpty) {
    for (a <- answers ) {
      SQL("INSERT INTO answers (question_id, text) VALUES ({qid}, {text});")
        .on('qid -> idMap(a.questionId), 'text -> a.text).execute()
    }
  }
}