2016-05-19 3 views
1

Обычно вы выполняете два или более оператора транзакции. Но во всех примерах, которые я мог найти при использовании transactionally в Slick 3, для понимания этих операторов необходимо понять, когда я обычно использую for в цикле.Использование транзакций в Slick 3

Это работает (удаление из двух таблиц в транзакции):

val action = db.run((for { 
     _ <- table1.filter(_.id1 === id).delete 
     _ <- table2.filter(_.id2=== id).delete 
    } yield()).transactionally) 
    val result = Await.result(action, Duration.Inf) 

Но это for/yield нужно? есть ли альтернативный способ запуска двух или более операторов транзакции?

ответ

4

Вы можете использовать transactionally на каждые DBIOAction, а не только те, которые являются результатом понимания. Например, вы можете использовать transactionally в сочетании с DBIO.seq методом, который принимает последовательность действий и запускает их последовательно:

val firstAction = table1.filter(_.id === id1).delete 
val secondAction = table2.filter(_.id === id2).delete 

val combinedAction = DBIO.seq(
    firstAction, 
    secondAction 
).transactionally 
4

Для вашего случая for/yield - это не единственный способ получить то, что вам нужно. Но вам придется подставить его для эквивалентного представления. Для понимания является syntactic sugar для комбинации flatMap s и map. Мы должны использовать их, потому что мы используем монадический состав для агрегирования всех действий в BDIOAction. Таким образом, вы могли бы также написать:

val action = db.run(
    table1.filter(_.id1 === id).delete.map (_ => 
    table2.filter(_.id2=== id).delete 
).transactionally 
) 
val result = Await.result(action, Duration.Inf) 

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

Давайте посмотрим на пример с 4-операторов в сделках, чтобы увидеть, как это выглядит:

  • Это было бы с для понимания:

    val action = db.run((for { 
        _ <- table1.filter(_.id1 === id).delete 
        _ <- table2.filter(_.id2=== id).delete 
        _ <- table3.filter(_.id3=== id).delete 
        _ <- table4.filter(_.id4=== id).delete 
    } yield()).transactionally) 
    val result = Await.result(action, Duration.Inf) 
    
  • Это было бы с flatMap/map s:

    val action = db.run(
        table1.filter(_.id1 === id).delete.flatMap (_ => 
        table2.filter(_.id2 === id).delete.flatMap (_ => 
         table3.filter(_.id3 === id).delete.map (_ => 
         table4.filter(_.id4=== id).delete 
        ) 
        ) 
    ).transactionally 
    ) 
    val result = Await.result(action, Duration.Inf) 
    
+0

Ваши примеры кажутся неправильными. Каждый из вызовов 'map' должен фактически быть вызовами« flatMap », иначе, если последнее действие на карте не будет выполнено, оно просто создаст действие и отменит его. –

Смежные вопросы