我发现自己需要将一系列具有嵌套元素序列的元素插入到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或两者中,我必须执行以下操作,最好是在单个事务中:
我是Scala Play的新手,所以我可能做了一些我不应该做的假设。任何让我开始的想法都会受到赞赏。
答案 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()
}
}
}