2015-05-21 11 views
10

Ho recentemente passato da Slick-2 a Slick-3. Tutto funziona molto bene con slick-3. Tuttavia, sto avendo alcuni problemi quando si tratta di transazione. Ho visto diverse domande e codice di esempio in cui sono utilizzati transactionally e withPinnedSession per gestire la transazione. Ma il mio caso è leggermente diverso. Sia transazionale che withPinnedSession possono essere applicati su Query. Ma quello che voglio fare è passare la stessa sessione a un altro metodo che eseguirà alcune operazioni e che vorrebbe racchiudere più metodi nella stessa transazione.Condivisione della sessione del database tra più metodi in Slick 3

Ho il codice slick-2 di seguito, non sono sicuro di come questo possa essere implementato con Slick-3.

def insertWithTransaction(row: TTable#TableElementType)(implicit session: Session) = { 
     val entity = (query returning query.map(obj => obj) += row).asInstanceOf[TEntity] 
     // do some operations after insert 
     //eg: invoke another method for sending the notification 
     entity 
} 

override def insert(row: TTable#TableElementType) = { 
    db.withSession { 
     implicit session => { 
     insertWithTransaction(row) 
     } 
    } 
} 

Ora, se qualcuno non è interessato ad avere transazioni, si può semplicemente richiamare il metodo insert(). Se è necessario eseguire alcune transazioni, è possibile farlo utilizzando insertWithTransaction() nel blocco db.withTransaction.

Per esempio:

db.withTransaction { implicit session => 
    insertWithTransaction(row1) 
    insertWithTransaction(row2) 
    //check some condition, invoke session.rollback if something goes wrong 
} 

Ma con lisciare-3, il transazionale può essere applicato solo su richiesta. Ciò significa che, ovunque sia necessario eseguire una logica centralizzata dopo l'inserimento, è possibile. Ogni sviluppatore deve gestire manualmente tali scenari in modo esplicito, se utilizzano le transazioni. Credo che questo potrebbe potenzialmente causare errori. Sto cercando di astrarre l'intera logica nell'operazione di inserimento in modo che gli implementatori debbano preoccuparsi solo della transazione successo/fallimento

C'è qualche altro modo, in slick-3, in cui posso passare la stessa sessione a più metodi in modo che tutto possa essere fatto in una singola sessione db.

risposta

1

Ti manca qualcosa: .transactionnaly non si applica a un Query, ma a un DBIOAction. Quindi, un DBIOAction può essere composto da più query utilizzando la composizione monadica.

Questo vuole essere un exemple proveniente dalla documentazione:

val action = (for { 
    ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result 
    _ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*) 
} yield()).transactionally 

action è composto da una query select e come molti delete query come righe restituite dalla prima query. Tutto ciò che crea DBIOAction da eseguire in una transazione.

Poi, per eseguire l'azione contro il database, è necessario chiamare db.run, quindi, in questo modo:

val f: Future[Unit] = db.run(action) 

Ora, per tornare al tuo exemple, diciamo che si desidera applicare un update interrogazione dopo il tuo inserto, puoi creare un'azione in questo modo

Spero che sia d'aiuto.

Problemi correlati