Łączenie za pomocą transaktora
Skonfiguruje Pan/Pani dostęp do bazy danych.
Łączenie za pomocą transaktora to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Scala for Backend Engineering & Functional Programming, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.
Czym jest Transactor?
Doobie to czysto funkcyjna warstwa JDBC dla Scali. Transactor[F] łączy czyste programy Doobie z rzeczywistym połączeniem z bazą danych.
Transactor wie, jak pozyskać obiekt JDBC Connection, uruchomić program w ramach transakcji i bezpiecznie zwolnić zasoby.
Jest parametryzowany typem efektu F[_], takim jak cats.effect.IO.
import doobie._
import cats.effect.IO
val xa: Transactor[IO] = ???Program ConnectionIO
Zapytania Doobie mają typ ConnectionIO[A]. Opisują obliczenie wymagające połączenia JDBC, ale jeszcze go nie uruchamiają.
Programy te buduje się w sposób czysty, a następnie przekazuje do Transactora w celu wykonania. Dopóki program nie zostanie uruchomiony, nie dotyka on bazy danych.
import doobie.implicits._
val program: ConnectionIO[Int] =
sql"select 42".query[Int].uniqueDriverManagerTransactor
Najprostszym Transactorem jest Transactor.fromDriverManager. Otwiera on zupełnie nowe połączenie dla każdej transakcji, używając JDBC DriverManager.
Wymaga nazwy klasy sterownika, adresu URL JDBC, nazwy użytkownika i hasła. Nadaje się do testów i skryptów, ale nie zapewnia puli połączeń.
val xa = Transactor.fromDriverManager[IO](
driver = "org.postgresql.Driver",
url = "jdbc:postgresql://localhost:5432/app",
user = "postgres",
password = "secret",
logHandler = None
)Uruchamianie programu
Aby wykonać obiekt ConnectionIO, należy wywołać .transact(xa). Zwraca to F[A], w tym przypadku IO[A].
Transactor opakowuje program w transakcję: zatwierdza ją po pomyślnym wykonaniu i wycofuje po błędzie, a połączenie zwalnia w obu przypadkach.
import doobie.implicits._
val result: IO[Int] =
sql"select 42".query[Int].unique.transact(xa)Pula połączeń z HikariCP
W środowisku produkcyjnym potrzebna jest pula połączeń. Doobie udostępnia HikariTransactor, oparty na HikariCP.
Tworzy się go jako Resource, dzięki czemu pula jest prawidłowo zamykana. Należy również przekazać kontekst wykonania dla blokujących operacji JDBC.
import doobie.hikari.HikariTransactor
import cats.effect.IO
val xaRes: Resource[IO, HikariTransactor[IO]] =
HikariTransactor.newHikariTransactor[IO](
"org.postgresql.Driver",
"jdbc:postgresql://localhost/app",
"postgres", "secret",
connectEC
)Dlaczego Resource?
Transactor korzystający z puli posiada długotrwały stan: otwarte połączenia i wątki działające w tle. Resource[F, A] gwarantuje powiązanie pozyskania ze zwolnieniem zasobów nawet w przypadku błędów lub anulowania.
Zwykle tworzy się Transactor raz podczas uruchamiania aplikacji i używa go przez cały czas jej działania.
xaRes.use { xa =>
program.transact(xa)
}Pula connectEC
HikariCP potrzebuje ExecutionContext, aby oczekiwać na połączenia z puli. Doobie udostępnia w tym celu ExecutionContexts.fixedThreadPool, który sam jest obiektem Resource.
Oddzielenie go od puli obliczeniowej zapobiega zagłodzeniu zadań zależnych od procesora przez blokujące pozyskiwanie połączeń.
import doobie.util.ExecutionContexts
val poolRes =
for {
ec <- ExecutionContexts.fixedThreadPool[IO](8)
xa <- HikariTransactor.newHikariTransactor[IO](
"org.postgresql.Driver", url, user, pass, ec)
} yield xaKonfigurowanie istniejącego DataSource
Jeśli istnieje już skonfigurowany javax.sql.DataSource, na przykład dostrojona instancja Hikari, można opakować go bezpośrednio za pomocą Transactor.fromDataSource.
Jest to typowe rozwiązanie, gdy framework zarządza pulą, a Doobie ma jedynie z niej korzystać.
val xa = Transactor.fromDataSource[IO](
dataSource = myDataSource,
connectEC = connectEC
)Test dymny połączenia
Prostą kontrolą stanu jest wykonanie zapytania select 1 przez Transactor. Jeśli zwróci ono wynik, sterownik, adres URL i dane uwierzytelniające działają poprawnie.
To dobry pierwszy krok przed podłączeniem właściwych zapytań.
val check: IO[Int] =
sql"select 1".query[Int].unique.transact(xa)
// check.unsafeRunSync() == 1Wewnętrzne działanie Transactora: Strategy
Transactor jest zbudowany z interpreterów i obiektu Strategy. Strategy określa, co dzieje się wokół każdej transakcji: before, after, oops (w przypadku błędu) i always.
Domyślna strategia wyłącza tryb automatycznego zatwierdzania, zatwierdza transakcję po sukcesie, wycofuje ją po błędzie i zawsze zamyka połączenie.
import doobie.util.transactor.Strategy
val noCommit = xa.copy(
strategy0 = Strategy.default.copy(after = doobie.free.connection.unit)
)Logowanie i obserwowalność
Doobie może rejestrować każde polecenie, jego argumenty i czas wykonania. We współczesnych wersjach instancję LogHandler[F] dołącza się do każdego zapytania, a nie do każdego Transactora.
Jest to niezwykle przydatne do wykrywania wolnych zapytań i sprawdzania wiązania parametrów w środowisku produkcyjnym.
import doobie.util.log._
val handler: LogHandler[IO] = (ev: LogEvent) =>
IO.println(ev.sql)Szybkie sprawdzenie
Sprawdź swoją wiedzę o Transactorach.
Podsumowanie
Transactor[F] łączy czyste programy ConnectionIO z rzeczywistą bazą danych. fromDriverManager nadaje się do testów, a HikariTransactor i fromDataSource do środowiska produkcyjnego dzięki wykorzystaniu puli.
Pulowane Transactory należy budować jako obiekty Resource, uruchamiać programy za pomocą .transact(xa) i pozwolić domyślnej strategii obsłużyć zatwierdzanie, wycofywanie oraz sprzątanie zasobów.
Ucz się Scala dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 39
- Lekcje
- 143
Często zadawane pytania
Czy lekcja „Łączenie za pomocą transaktora” jest bezpłatna?
Tak — pełny tekst „Łączenie za pomocą transaktora” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Scala for Backend Engineering & Functional Programming, przejdź na CoddyKit PRO. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.
Co nauczysz się w „Łączenie za pomocą transaktora”?
Skonfiguruje Pan/Pani dostęp do bazy danych. Ćwiczysz Scala for Backend Engineering & Functional Programming z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Scala for Backend Engineering & Functional Programming?
Nie wymagamy żadnego doświadczenia. Scala for Backend Engineering & Functional Programming w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Łączenie za pomocą transaktora”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Scala for Backend Engineering & Functional Programming?
Tak. Każda lekcja Scala for Backend Engineering & Functional Programming zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Łączenie za pomocą transaktora
- Wykonywanie zapytań
- Wstawianie i aktualizowanie
- Komponowanie transakcji