Slick:两次查询,一次交易

Slick: two queries, one transaction

假设我有两个 tables:

people:

id: long | uuid: UUID     | name: String

----

cars

id: long | owner_id: long | name: String

其中 ownerpeople.id 的外键。

我有一个查询 select 所有车主的 uuid(只是一个 API 设计)。

问题是:如何在一个事务中执行以下查询,我必须通过其 uuid (SELECT id from people where uuid = ?) 获得 people.id 然后 SELECT * from cars where owner_id = id

当然,我一开始可以通过它的uuidpeopletable得到id,比如

val ownerId = db run people.filter(_.uuid === uuid.bind).map(_.id).result.head

然后 运行 对 select 汽车的另一个​​查询 owner_id:

val cars = ownerId.flatMap { 
  id => db run cars.filter(_.ownerId === id).result 
}

但这不会在一次交易中发生。有什么想法吗?

我会说:

val groupByQuery =  cars.join(people)
 .on (_.owner_id === _.id)
 .map{
  case (car, owner) => (owner.uuid, car)
 }
.groupBy(_._1)

db.run(groupByQuery)

有一个 transactionally 的方法来进行巧妙的操作。你应该使用:

import slick.driver.PostgresDriver.api._  // for example

val query = for {
  p <- peoples.filter(_.uuid === "some-id")
  c <- cars.filter(_.owner_id === p.uuid)
} yield (p, c)

val action = query.result
val transactionalAction = action.transactionally // will be executed 
                                                 // in single transaction

// Ungrouped result
// TODO: You can group on db side by your query or 
// on client side using groupBy from collection API
val result:Future[Seq[(People, Cars)]] = db.run(transactionalAction)