2015-07-09 7 views
5

Provo a migrare l'applicazione a Slick 3.0. Vorrei fare una transazione per Slick 3.0. So come farlo ma vorrei chiedere la struttura delle classi. prega di dare un'occhiata sul repository di esempio:Come strutturare il livello di accesso al database con le transazioni

alcuni repository (o DAO) per Slick 2.1:

class UserRepository { 
    def all()(implicit: Session): Seq[User] = users.run 
    def insert(user: User)(implicit: Session): Int = users.insert(user) 
    ... 
} 

class CarRepository { 
    def all()(implicit: Session): Seq[Car] = cars.run 
    def insert(car: Car)(implicit: Session): Int = cars.insert(car) 
    ... 
} 

Per fare l'operazione in Slick 2.1 ho potuto creare un servizio dove posso fare la transazione :

così attualmente ho repository (o DAO) per l'accesso al database e servizi per la logica più generale.

alcuni repository (o DAO) per Slick 3.0:

class UserRepository { 
    def all(): Future[Seq[User]] = db.run(Users.result) 
    def insert(user: User): Future[Int] = db.run(Users += user) 

    ... 
} 

class CarRepository { 
    def all(): Future[Seq[Car]] = db.run(Cars.result) 
    def insert(car: Car): Future[Int] = db.run(Cars += car) 
    ... 
} 

In Slick 3.0 possiamo fare la transazione sul DBIOActions ma quando abbiamo la struttura come mostrato in precedenza che non è possibile a causa della futures. Potrei creare alcune classi UserCarRepository per fare la transazione, ma penso che non sia la migliore. Per superare questa situazione espongo DBIOActions in repository (o DAO) e quindi in altri layer mix DBIOActions dagli User e Car repository in una transazione per restituire Future alla fine (il prossimo livello potrebbe essere un servizio per operare su futures) . Quando abbiamo più repository per la transazione potrebbe essere un po 'disordinato.

Come strutturare questo per Slick 3.0? Come ottenere un accoppiamento più libero per la transazione su diversi repository?

lettura: https://github.com/playframework/play-slick/tree/master/samples https://github.com/slick/slick/issues/1084 https://groups.google.com/forum/#!topic/scalaquery/32cO7lHbxOs

risposta

1

Tenere gli inserti come DBIOActions più a lungo possibile, comporli in base alle esigenze e quindi fare l'attuale DB-query. Sketch:

class UserRepository { 
    def all() = Users.result 
    def insert(user: User) = Users += user 

    ... 
} 

class CarRepository { 
    def all() = Cars.result 
    def insert(car: Car) = Cars += car 
    ... 
} 

val composedInserts = (for { 
    _ <- new UserRepository().insert(user) 
    _ <- new CarRepository().insert(car) 
} yield()).result 

db.run(composedInserts.transactionally) 

Edit: chiarito messaggio

+0

Potrebbe essere ok, ma quando mescoliamo l'accesso a diverse tabelle si rompe singola responsabilità. Come ti piacerebbe strutturare questo? Suppongo che la tua soluzione mantenga l'accesso in una classe. – piobab

+0

Forse ero un po 'oscuro in quello che intendevo. Ho modificato la risposta e aggiunto un po 'di contesto. Se vuoi, puoi inserire il codice che esegue le query db effettive in una classe, oppure puoi unirle nel resto del codice e tenere a mente mentalmente quando esegui le query in formato db, a seconda di cosa ti senti a tuo agio. – Rikard