Mam problemy ze zrozumieniem nowego interfejsu API Slick DBIOAction
, który nie ma wielu przykładów w dokumentach. Korzystam z wersji Slick 3.0.0 i potrzebuję wykonać pewne działania bazy danych, a także niektóre obliczenia z danymi otrzymanymi z bazy danych, ale wszystkie te działania muszą zostać wykonane w ramach jednej transakcji. Próbuję wykonać następujące czynności:Wykonywanie operacji innych niż bazy danych w transakcji w Slick 3
- Wykonaj zapytanie do bazy danych (tabela
types
). - Dokonaj pewnych agregacji i filtrowania wyników zapytania (tego obliczenia nie można wykonać w bazie danych).
- Wykonaj inne zapytanie, na podstawie obliczeń z kroku 2 (tabela
messages
- z powodu pewnych ograniczeń zapytanie to musi być w surowym słowie SQL). - Dołącz dane z kroku 2 i 3 do pamięci.
Chcę, aby zapytania z etapów 1 i 3 były wykonywane w ramach transakcji, ponieważ dane z ich zestawów wyników muszą być spójne.
Próbowałem to zrobić w monadycznym stylu łączenia. Oto nadmiernie uproszczona wersja mojego kodu, ale nawet nie mogę zmusić go do kompilacji:
val compositeAction = (for {
rawTypes <- TableQuery[DBType].result
(projectId, types) <- rawTypes.groupBy(_.projectId).toSeq.map(group => (group._1, group._2.slice(0, 10)))
counts <- DBIO.sequence(types.map(aType => sql"""select count(*) from messages where type_id = ${aType.id}""".as[Int]))
} yield (projectId, types.zip(counts))).transactionally
- Pierwszy wiersz
for
pojmowania wybiera dane z tabelitypes
. - Drugi rząd
for
pojmowania ma robić pewne ugrupowania i krojenie wyników, w wynikuSeq[(Option[String], Seq[String])]
- Trzeci rząd
for
pojmowania musi wykonać szereg zapytań dla każdego elementu z poprzedniego etapu, w w szczególności, musi wykonać pojedynczą kwerendę SQL dla każdej wartości z zakresuSeq[String]
. Tak więc w trzecim rzędzie buduję sekwencjęDBIOAction
s. - Klauzula
yield
z drugiego etapu icounts
z trzeciego etapu.
Konstrukcja ta jednak nie działa i daje dwa błędy kompilacji czas:
Error:(129, 16) type mismatch;
found : slick.dbio.DBIOAction[(Option[String], Seq[(com.centreit.proto.repiso.storage.db.models.DBType#TableElementType, Vector[Int])]),slick.dbio.NoStream,slick.dbio.Effect]
(which expands to) slick.dbio.DBIOAction[(Option[String], Seq[(com.centreit.proto.repiso.storage.db.models.TypeModel, Vector[Int])]),slick.dbio.NoStream,slick.dbio.Effect]
required: scala.collection.GenTraversableOnce[?]
counts <- DBIO.sequence(types.map(aType => sql"""select count(*) from messages where type_id = ${aType.id}""".as[Int]))
^
Error:(128, 28) type mismatch;
found : Seq[Nothing]
required: slick.dbio.DBIOAction[?,?,?]
(projectId, types) <- rawTypes.groupBy(_.projectId).toSeq.map(group => (group._1, group._2.slice(0, 10)))
^
Próbowałem owinąć drugą linię w DBIOAction
za pomocą DBIO.successful
, która ma podnieść stała wartość do DBIOAction
monady:
(projectId, types) <- DBIO.successful(rawTypes.groupBy(_.projectId).toSeq.map(group => (group._1, group._2.slice(0, 10))))
Ale w tym kodzie zmienna types
wnioskuje się Any
, a kod robi nie skompilować z tego powodu.
spojrzeć na tym przykładzie [] (https://github.com/slick/slick/issues/1093#issuecomment-110252046) i sprawdzić, czy to pomaga –
@FelipeAlmeida Dzięki, ale to nie jest to, czego potrzebuję. W tym przykładzie wszystkie instrukcje są aktualizacjami/usuwaniem/wstawkami i nie są wzajemnie powiązane przez ich wyniki i nie dają niczego (wszystkie lewe części to '_').W moim przypadku jedno z moich działań w ogóle nie ma nic wspólnego z bazą danych, a wszystkie działania zwracają wyniki, które są używane w innych wyrażeniach lub w "wydaniu". –