2016-05-19 2 views
1

Généralement, vous exécutez deux instructions ou plus dans une transaction. Mais dans tous les exemples que j'ai pu trouver en utilisant transactionally dans Slick 3, il y a un moyen de comprendre ces groupes, quand j'utilise habituellement le for en boucle.Utilisation transactionnelle dans Slick 3

Cela fonctionne (suppression de deux tables dans une transaction):

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

Mais est le for/yield nécessaire? existe-t-il une alternative pour exécuter deux instructions ou plus dans une transaction?

Répondre

4

Vous pouvez utiliser transactionally sur chaque DBIOAction, pas seulement ceux qui sont le résultat de la compréhension pour. Par exemple, vous pouvez utiliser transactionally en combinaison avec la méthode DBIO.seq, qui prend une séquence d'actions et les exécute successivement:

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

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

Pour votre cas for/yield n'est pas la seule façon d'obtenir ce que vous avez besoin. Mais vous devrez le remplacer par la représentation équivalente. La pour la compréhension est syntactic sugar pour une combinaison de flatMap s et un map. Nous devons les utiliser car nous utilisons la composition monadique pour agréger toutes les actions dans un BDIOAction. Vous pouvez aussi écrire comme:

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

La compréhension pour est généralement utilisé car est plus propre, plus facile à comprendre et très facile à l'échelle.

Permet de jeter un oeil à un exemple avec 4 déclarations dans une transaction pour voir à quoi il ressemble:

  • Ce serait une pour la compréhension:

    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) 
    
  • Ce serait avec 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

Vos exemples semblent être incorrectes. Chacun des appels 'map' devrait en fait être des appels' flatMap', sinon la dernière action de map ne sera pas exécutée, elle créerait simplement une action et la supprimerait. –