SLICK 3.0 - несколько запросов в зависимости друг от друга - db.run(действие)
Я новичок в Slick 3 и до сих пор я понял, что db.run - это асинхронный вызов..map или.flatMap запускается после возвращения Future.
Проблема в моем коде ниже состоит в том, что все подзапросы не работают (вложенный db.run).
Концептуально говоря, что я не получаю? Допустимо ли делать такой код, как показано ниже? в основном в.map первого запроса я делаю некоторые действия в зависимости от первого запроса.
Я вижу повсюду циклы с выходом, это единственный путь? Связана ли проблема в моем коде с возвращенным значением Future?
val enterprises = TableQuery[Enterprise]
val salaries = TableQuery[Salary]
//Check if entered enterprise exists
val enterpriseQS = enterprises.filter(p => p.name.toUpperCase.trim === salaryItem.enterpriseName.toUpperCase.trim).result
val result=db.run(enterpriseQS.headOption).map(_ match
{
case Some(n) => {
//if an enterprise exists use the ID from enterprise (n.id) when adding a record to salary table
val addSalary1 = salaries += new SalaryRow(0, n.id, salaryItem.worker)
db.run(addSalary1)
}
case None => {
//if an enterprise with salaryItem.enterpriseName doesn't exist, a new enterprise is inserted in DB
val enterpriseId = (enterprises returning enterprises.map(_.id)) += EnterpriseRow(0, salaryItem.enterpriseName)
db.run(enterpriseId).map{
e => {
val salaryAdd2 = salaries += new SalaryRow(0, e, salaryItem.worker)
db.run(salaryAdd2)
}
}
}
})
1 ответ
Проблема в моем коде ниже заключается в том, что все подзапросы не работают (вложенный db.run)
Я подозреваю, что вы в конечном итоге с вложенными Future[R]
Результаты. Я не исследовал это все же. Так как...
Концептуально говоря, что я не получаю?
То, как я бы занялся этим, это посмотреть на объединение DBIO[R]
, Это может быть концепция, которая помогает.
То, что вы делаете, это пытаетесь выполнить каждое действие (запрос, вставка...) индивидуально. Вместо этого объедините отдельные действия в одно действие и запустите его.
Я бы переписал основную логику так:
val action: DBIO[Int] = for {
existingEnterprise <- enterpriseQS.headOption
rowsAffected <- existingEnterprise match {
case Some(n) => salaries += new SalaryRow(0, n.id, salaryItem.worker)
case None => createNewEnterprise(salaryItem)
}
} yield rowsAffected
Для None
В этом случае я бы создал вспомогательный метод:
def createNewEnterprise(salaryItem: SalaryItem): DBIO[Int] = for {
eId <- (enterprises returning enterprises.map(_.id)) += EnterpriseRow(0, salaryItem.enterpriseName)
rowsAffected <- salaries += new SalaryRow(0, eId, salaryItem.worker)
} yield rowsAffected
Наконец, мы можем запустить это:
val future: Future[Int] = db.run(action)
// or db.run(action.transactionally)
val result = Await.result(future, 2 seconds)
println(s"Result of action is: $result")
Вторая половина поста в блоге, который я написал, больше говорит об этом.
Код, который я использовал: https://github.com/d6y/so-31471590