SLICK 3.0 - 多个查询相互依赖 - db.run(action)
SLICK 3.0 - multiple queries depending on one another - db.run(action)
我是 Slick 3 的新手,到目前为止我知道 db.run 是异步调用。返回 Future 后,.map 或 .flatMap 为 运行。
我下面的代码中的问题是所有子查询都不起作用(嵌套 db.run)。
从概念上讲,我没有得到什么?执行以下此类代码是否有效?基本上在第一个查询的 .map 中,我根据第一个查询执行一些操作。
我到处都看到 for 循环和 yield,这是唯一的方法吗?我的代码中的问题是否与返回的 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)
}
}
}
})
The problem in my code below is that all the sub queries do not work (nested db.run)
我怀疑您最终得到的是嵌套的 Future[R]
结果。不过我还没有调查过。因为...
Conceptually speaking, what am I not getting?
我解决这个问题的方法是考虑合并 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")
blog post I've written 的后半部分对此进行了更多讨论。
我是 Slick 3 的新手,到目前为止我知道 db.run 是异步调用。返回 Future 后,.map 或 .flatMap 为 运行。
我下面的代码中的问题是所有子查询都不起作用(嵌套 db.run)。
从概念上讲,我没有得到什么?执行以下此类代码是否有效?基本上在第一个查询的 .map 中,我根据第一个查询执行一些操作。
我到处都看到 for 循环和 yield,这是唯一的方法吗?我的代码中的问题是否与返回的 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)
}
}
}
})
The problem in my code below is that all the sub queries do not work (nested db.run)
我怀疑您最终得到的是嵌套的 Future[R]
结果。不过我还没有调查过。因为...
Conceptually speaking, what am I not getting?
我解决这个问题的方法是考虑合并 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")
blog post I've written 的后半部分对此进行了更多讨论。