2015-06-28 10 views
22

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

  1. Wykonaj zapytanie do bazy danych (tabela types).
  2. Dokonaj pewnych agregacji i filtrowania wyników zapytania (tego obliczenia nie można wykonać w bazie danych).
  3. Wykonaj inne zapytanie, na podstawie obliczeń z kroku 2 (tabela messages - z powodu pewnych ograniczeń zapytanie to musi być w surowym słowie SQL).
  4. 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 
  1. Pierwszy wiersz for pojmowania wybiera dane z tabeli types.
  2. Drugi rząd for pojmowania ma robić pewne ugrupowania i krojenie wyników, w wyniku Seq[(Option[String], Seq[String])]
  3. 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 zakresu Seq[String]. Tak więc w trzecim rzędzie buduję sekwencję DBIOAction s.
  4. Klauzula yield z drugiego etapu i counts 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.

+0

spojrzeć na tym przykładzie [] (https://github.com/slick/slick/issues/1093#issuecomment-110252046) i sprawdzić, czy to pomaga –

+0

@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". –

Odpowiedz

15

Spróbuj to tak:

val compositeAction = (for { 
    rawTypes <- TableQuery[DBType].result 
    pair <- DBIO.sequence(rawTypes.groupBy(_.projectId).toSeq.map(group => DBIO.successful(group))) 
    counts <- DBIO.sequence(pair.head._2.map(aType => sql"""select count(*) from messages where type_id = ${aType.id}""".as[Int])) 
} yield (pair.head._1, pair.head._2.zip(counts))).transactionally 
+0

Dzięki! To wydaje się być tym, czego szukałem. –

Powiązane problemy