2016-01-23 15 views
5

to pytanie jest o gładkie 3,0 lub 3,1 (Ja elastycznie iż)Scala + Slick 3: Wprowadzanie wynik jednego zapytania do innej tabeli

mam zapytanie pośrednią, która przetwarzać z map, for, etc. Aby uzyskać pożądany wynik. W końcu mam

val foo: DBIOAction[Seq[MySchema.Bar], NoStream, Effect.Read] 

Teraz mam val bar: TableQuery[MySchema.Bar] i chcę wstawić foo w niej.

Jeśli foo byłby Seq, mógłbym po prostu zrobić bar ++= foo, ale tak nie jest.

Jedyny sposób, jaki znalazłem, to zmaterializować wynik, oczekując na niego. Podoba Ci się to

val query = (bar ++= Await.result(db.run(foo), Duration.Inf)) 

Oczywiście query musi być prowadzony w pewnym momencie z db.run. Ale teraz mam dwa przebiegi DB. Czy nie byłoby lepiej mieć wszystko w jednym biegu?

Czy jest lepszy sposób to zrobić?

+0

'bar + = foo'? Ale nadal musiałbyś "db.run" go bez względu na to, czy jest to '+ =' czy '++ =' ... (?) – kornfridge

+0

Myślę, że ++ = z efektami ubocznymi był slick2 api, podczas gdy slick3 jest bardziej funkcjonalny, więc wymaga jawnego zrobienia 'db.run' – kornfridge

+0

Tak, wynik ++ = jest teraz zapytaniem, które należy uruchomić. W tym punkcie zredagowałem pytanie. Ale muszę wykonać dwa wywołania db.run dla tego zadania. – masgo

Odpowiedz

4

DBIOAction ma map/flatMap funkcji, więc można napisać coś podobnego

val insertAction = foo.flatMap(bar ++= _) 

insertAction będzie od rodzaju DBIOAction[Int, NoStream, Effect.Write] czy coś takiego (nie jestem całkowicie pewien Int i efekt) następnie można go uruchomić na DB jak każdy DBIOAction przy użyciu db.run; to, co otrzymasz, to przyszłość ogólnego zapytania i wyniku wstawienia.

+0

"FlatMap" załatwia sprawę. Na koniec mam tylko jedną DBIOAction, którą muszę uruchomić. W tym temacie natknąłem się na inną rzecz: Kiedy powinienem zrobić program db.run()? Oto przykład 'val foo = db.run (persons.result.map (_. map {p => tr (td (p.id))})) 'Mogę to zrobić w ten sposób, lub mógłbym zakończyć część' db.run' po '.result '. Obie metody dają mi taką samą "Przyszłość", czy jest jakaś różnica pod względem wydajności? – masgo

+2

Ogólnie rzecz biorąc, chcesz pracować na poziomie 'DBIO' w miarę możliwości; gdy wywołasz 'db.run', slick będzie działał tak, jak wiele zapytań jest potrzebnych, używając własnego kontekstu wykonania, i zwróci ci' Przyszłość'. Myślę, że istnieje potencjalna różnica w wydajności, jeśli to zrobisz, ponieważ zoptymalizujesz użycie wątków w odniesieniu do dostępu do bazy danych. –

1

Na pytania już udzielono odpowiedzi, ale przyjechałem tutaj, szukając innego rozwiązania, więc może to będzie pomocne dla innych osób.

Jak mówi @Aldo, chcemy pracować na poziomie DBIO tak dalece, jak to możliwe, ale chciałbym pójść dalej i powiedzieć, że powinieneś pracować na poziomie Query w miarę możliwości, ponieważ kompiluje to do pojedynczego zdania sql, które można wysłać do bazy danych.

Na przykład wstawkę z zaznaczenia należy skompilować do INSERT INTO table1 SELECT.... Jeśli używasz wielu DBIOS przy użyciu flatMap, tak jak zasugerowano, zostanie on skompilowany do SELECT, wartości zostaną wprowadzone do pamięci, a następnie zostanie skompilowane oświadczenie INSERT, interpolujące wartości w ciągu, a to nowe zapytanie zostanie wysłane do Baza danych. W rzeczywistości może to być znacznie wolniejsze, jeśli twój wybór zwraca wiele wyników i może wyczerpać pamięć w najgorszym przypadku.

więc skompilować coś takiego w jednym zapytaniu można napisać:

val bar: TableQuery[MySchema.Bar] 

val foo: Query[MySchema.Bar, Bar, Seq] 

val insert: DBIO[Int] = bar.forceInsertAll(foo) 
Powiązane problemy