Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 未能在Quill中使用事务插入一对多关系对象_Mysql_Sql_Scala_Quill.io - Fatal编程技术网

Mysql 未能在Quill中使用事务插入一对多关系对象

Mysql 未能在Quill中使用事务插入一对多关系对象,mysql,sql,scala,quill.io,Mysql,Sql,Scala,Quill.io,我有一个人表和动物表,动物表中有FK to personId,因为它们之间有一对多的关系 我只想创建一个人,并使用事务创建它的动物,因为我希望这个过程是原子的(如果我不能创建它的动物,数据库中就没有人的用处) 这是我如何接受人员创建请求的模型: case class PersonCreateRequest(name: String, age: Int, animals: Seq[AnimalCreateRequest]) 以下是DB认识一个人的方式: case class Person(per

我有一个人表和动物表,动物表中有FK to personId,因为它们之间有一对多的关系

我只想创建一个人,并使用事务创建它的动物,因为我希望这个过程是原子的(如果我不能创建它的动物,数据库中就没有人的用处)

这是我如何接受人员创建请求的模型:

case class PersonCreateRequest(name: String, age: Int, animals: Seq[AnimalCreateRequest])
以下是DB认识一个人的方式:

case class Person(personId: Long, name, age: Int)

// this is just a companion object to help me take a PersonCreateRequest and make it Person
object Person {
  def apply(person: PersonCreateRequest): Person = {
    Person(0L,
           person.name,
           person.age)
  }
}
和我对动物的看法一样:

case class AnimalCreateRequest(animalType: String, age: Int)
这是db了解动物的方式(personId=所有者):

所以现在我试着这么做(但失败了):

lazy val ctx = new MysqlAsyncContext(CamelCase, "ctx")
  import ctx._


  def insertPerson(personToCreate: PersonCreateRequest): Future[Long] = {

    // getting the person object that the db knows
    val dbPerson = Person.apply(personToCreate)

    // INSERT Person Query
    val insertPersonQuery = quote {
      query[Person].insert(lift(dbPerson)).returning(_.personId)
    }

    ctx.transaction { implicit ec =>
      for {
        personId   <- ctx.run(insertPersonQuery)
        contactIds <- {
          Future.sequence(
          personToCreate.animals.map(animal => {
            val animalToInsert = Animal.apply(animal, personId)
            insertAnimal(animalToInsert)
          })
          )
        }
      } yield personId
    }
  }

  def insertAnimal(animal: Animal): Future[Long] = {
    val q = quote {
      query[Animal].insert(lift(animal)).returning(_.animalId)
    }
    ctx.run(q)
  }
lazy val ctx=new MysqlAsyncContext(CamelCase,“ctx”)
进口ctx_
def insertPerson(personToCreate:PersonCreateRequest):未来[Long]={
//获取数据库知道的person对象
val dbPerson=Person.apply(personToCreate)
//插入人员查询
val insertPersonQuery=报价单{
查询[Person].insert(lift(dbPerson)).returning(u.personId)
}
ctx.transaction{implicit ec=>
为了{

personId将隐式
ExecutionContext
参数添加到
insertAnimal
方法:

def insertAnimal(animal: Animal)(implicit ec: ExecutionContext): Future[Long] =
如果没有它,您将无法从事务块传递ec,动物插入将尝试使用池中的其他连接。

您熟悉吗

要从事务中获取结果,您应该将
onSuccess
处理程序添加到从
ctx.transaction
调用返回的
Future

ctx.transaction { ...
}.onSuccess {
  case personId => ...
}

问题是,目前Quill async不支持事务内部的并发操作

因此必须按顺序插入动物:

ctx.transaction { implicit ec =>
  for {
    personId <- ctx.run(insertPersonQuery)
    animals = personCreate.animals.map(Animal.apply(personId, _))
    _ <- animals.foldLeft(Future.successful(0l)) {
      case (fut, animal) =>
        fut.flatMap(_ => insertAnimal(animal))
    }
  } yield personId
}
ctx.transaction{implicit ec=>
为了{
拟人插入动物(动物))
}
}屈服人格
}
此外,更好的方法是使用批插入:)


感谢@fwbrasil和@mentegy的帮助!

请添加有关您所遇到错误的更多信息。@mixel发生的情况是,我没有得到回复…(添加到问题中)这是你处理这项任务的方式吗?我是这个图书馆的新手。为什么?我想把未来还给controllerOk,然后把它还给控制器处理。你写了“它一直在处理,没有返回任何东西或抛出错误”。那么这是什么意思呢?在我的控制器中,我有这样一个:
peopleDao.insertPerson(personToCreate.map{personId=>Ok(s“personId:$personId”)
这应该行得通,我只是没有得到答案……我真的想弄清楚到底发生了什么:/你应该添加最小但完整的示例来重现你的问题。这可能是http服务器库配置或其他方面的问题。你能在GitHub上创建示例项目吗?如果我导入
导入,为什么我需要它scala.concurrent.ExecutionContext.Implicits.{global=>ec}
,它不允许我同时拥有这两个:/如果您想在事务中执行查询,它们必须使用调用事务方法后隐式获得的ec。如果
insertAnimal
使用全局ec,那么这些插入将在事务之外运行。
ctx.transaction { implicit ec =>
  for {
    personId <- ctx.run(insertPersonQuery)
    animals = personCreate.animals.map(Animal.apply(personId, _))
    _ <- animals.foldLeft(Future.successful(0l)) {
      case (fut, animal) =>
        fut.flatMap(_ => insertAnimal(animal))
    }
  } yield personId
}