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

时间:2017-08-27 21:01:07

标签: scala anorm

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

我的数据如下所示。

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

在db中它看起来像这样:

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或两者中,我必须执行以下操作,最好是在单个事务中:

  • 问题中的foreach问题
    • 将问题插入问题
    • 回答中的foreach回答,其中answer.questionId == old question.id
      • 使用从问题插入
      • 获得的新问题ID将答案插入答案中

我是Scala Play的新手,所以我可能做了一些我不应该做的假设。任何让我开始的想法都会受到赞赏。

2 个答案:

答案 0 :(得分:0)

如其名称所示,Anorm不是ORM,也不会为您生成声明。

您必须确定适当的陈述来代表数据和关系(例如my Acolyte tutorial)。

至于事务,Anorm是一个围绕JDBC的瘦/智能包装器,因此保持JDBC事务语义。 BTW Play在其.withTransaction解析实用程序上提供DB

答案 1 :(得分:0)

我用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()
    }
  }
}