Удаление строк из нескольких таблиц в скользком запросе

Я погуглил и нашел эту тему Slick 3.0: удаление строк из нескольких таблиц в транзакции. Однако решение говорит, что это не очень хорошее решение.

Я удаляю строки из нескольких таблиц с моим кодом ниже

val deleteB = for {
  aId <- TableA.filter(a => a.id === param).map(_.id)
  bId <- TableB.filter(_.aId === aId)
} yield bId

val deleteC = for {
  aId <- TableA.filter(a => a.id === param).map(_.id)
  cId <- TableC.filter(_.aId === aId)
} yield cId

val deleteA = TableA.filter(a.Id === param)

val query = (deleteC.delete andThen deleteB.delete andThen deleteA.delete).transactionally
db.run(query)

Но мне интересно, есть ли лучший способ написать это.

Моя проблема с описанным выше подходом заключается в том, что я хочу вернуть количество строк, удаленных из TableA, а не сумму строк, удаленных из дочерних таблиц TableB и TableC.

Кроме того, во время выполнения он жалуется на наличие соединений в запросе на удаление.

2 ответа

Решение

Я думаю, что вы можете сделать это также -

 def buildTransactionQuery = {
    for {
      deleteA <- TableA.filter(a.Id === param)
      deleteB  <- TableB.filter(_.aId === deleteA.map(_.id))
      deleteC  <- TableC.filter(_.aId === deleteA.map(_.id))

      deleteAAction = deleteA.delete
      deleteBAction = deleteB.delete
      deleteCAction = deleteC.delete
      res = (deleteAAction, deleteBAction, deleteCAction)
    } yield res
  }

  def executeTransactionQuery = {
    val transactionQuery = for {
      queries <- buildTransactionQuery
      action = DBIOAction.seq(queries._3, queries._2, queries._1)
    } yield action
    transactionQuery.flatMap(action => db.run(action.transactionally).transform(s => true, t => {
      logger.error(t.getMessage)
      t
    }))
  }

Следующее исправит предупреждение о соединении / ошибка.

val deleteB = TableB.filter(_.aid in TableA.filter(a => a.id === id).map(_.id))

val deleteC = TableC.filter(_.aid in TableA.filter(a => a.id === id).map(_.id))

val deleteA = TableA.filter(_.id === id)

db.run((deleteB.delete andThen deleteC.delete andThen deleteA.delete).transactionally)

А поскольку вы используете andThen для цепочки своих действий, составленное действие всегда будет возвращать количество затронутых строк последнего действия, как указано здесь. Таким образом, возвращаемое число - это всегда строки, удаленные из deleteA действие, так как это последнее действие в andThen цепь.

а потом

Запустите другое действие после этого действия, если оно успешно выполнено, и верните результат второго действия. Если одно из двух действий завершается неудачей, полученное в результате действие также не выполняется.

Другие вопросы по тегам