2017-08-23 1 views
0

Je suis nouveau sur Slick et j'essaie de réécrire les deux requêtes suivantes pour travailler en une seule transaction. Mon but est de vérifier si 1. éléments existent 2. retour élément existant ou en créer, il gère autoincrement de MySQLPasser le résultat d'un DBIO dans un autre

Les deux fonctions sont les suivantes:

def createEmail(email: String): DBIO[Email] = { 
    // We create a projection of just the email column, since we're not inserting a value for the id column 
    (emails.map(p => p.email) 
     returning emails.map(_.id) 
     into ((email, id) => Email(id, email)) 
    ) += email 
    } 

    def findEmail(email: String): DBIO[Option[Email]] = 
    emails.filter(_.email === email).result.headOption 

Comment puis-je les enchaîner en toute sécurité, par exemple. pour exécuter d'abord vérifier l'existence, retourner si l'objet existe déjà et s'il n'existe pas alors le créer et retourner le nouvel élément dans une transaction?

Répondre

3

Vous pouvez utiliser une pour la compréhension:

def findOrCreate(email: String) = { 
    (for { 
    found <- findEmail(email) 
    em <- found match { 
     case Some(e) => DBIO.successful(e) 
     case None => createEmail(email) 
    } 
    } yield em).transactionally 
} 

val result = db.run(findOrCreate("[email protected]")) 
// Future[Email] 
+0

Et 'db.run (findOrCreate ("[email protected]") transactionnellement) 's'exécuter en une transaction. – liosedhel

+0

@liosedhel: Mise à jour. – chunjef

+0

Thx pour votre aide! Question secondaire - y a-t-il un moyen d'accéder à 'e' dans le pattern matching pour pointer sous ses éléments et les passer à' createEmail'? Alors que je peux faire, par exemple. 'createEmail (e.name)' – Niemand

1

Avec un peu d'aide de la bibliothèque de chats.

def findOrCreate(email: String): DBIO[Email] = { 
    OptionT(findEmail(email)).getOrElseF(createEmail(email)).transactionally 
}