2015-07-09 20 views
5

Próbuję przenieść aplikację do wersji Slick 3.0. Chciałbym dokonać transakcji dla Slick 3.0. Wiem, jak to zrobić, ale chciałbym poprosić o strukturę zajęć. Proszę spojrzeć na repozytoriach próbki:Jak skonstruować warstwę dostępu do bazy danych za pomocą transakcji

Niektóre repozytoriów (lub DAO) dla 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) 
    ... 
} 

W tym celu transakcji w Slick 2.1 mogłem stworzyć serwis, gdzie można zrobić transakcję :

db.withTransaction{ implicit session => 
    userRepository.insert(user) 
    carRepository.insert(car) 
} 

więc obecnie mam repozytoria (lub DAO) do dostępu do baz danych i usług dla bardziej ogólnej logiki.

Niektóre repozytoria (lub DAO) dla 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) 
    ... 
} 

W Slick 3,0 możemy zrobić transakcję na DBIOActions ale kiedy mamy strukturę jak pokazano powyżej nie jest możliwe ze względu na futures. Mogłem utworzyć pewną klasę UserCarRepository, aby wykonać transakcję, ale myślę, że nie jest najlepsza. Aby przezwyciężyć tę sytuację, wystawiam DBIOActions w repozytoriach (lub DAO), a następnie w innych warstwach DBIOActions z repozytoriów użytkowników i samochodów w jednej transakcji, aby zwrócić Future na końcu (kolejna warstwa może być usługą do obsługi kontraktów terminowych) . Gdy mamy więcej repozytoriów do transakcji, może to trochę zaśmiecać.

Jak skonstruować to dla wersji Slick 3.0? Jak uzyskać więcej luźnego sprzężenia dla transakcji na różnych repozytoriach?

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

Odpowiedz

1

Przechowywać wkładek jak DBIOActions tak długo, jak to możliwe, układać je w razie potrzeby, a następnie wykonaj rzeczywiste DB-zapytanie. Szkic:

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: wyjaśnić wiadomość

+0

To może być ok, ale kiedy wymieszać dostęp do różnych tabel łamie jeden odpowiedzialność. Jak chcesz to zorganizować? Przypuszczam, że twoje rozwiązanie zapewnia dostęp w jednej klasie. – piobab

+0

Byłem może trochę niejasny w tym, co miałem na myśli. Edytowałem odpowiedź i dodałem trochę kontekstu. Jeśli chcesz, możesz umieścić kod, który wykonuje faktyczne kwerendy db w jednej klasie, lub możesz połączyć je z resztą kodu i pamiętać tylko o tym, kiedy robisz zapytania db, w zależności od tego, co ci wygodnie. – Rikard