Mit einem Transactor verbinden
Richten Sie den Datenbankzugriff ein.
Mit einem Transactor verbinden ist eine kostenlose Scala for Backend Engineering & Functional Programming-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Scala for Backend Engineering & Functional Programming-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.
Was ist ein Transactor?
Doobie ist eine rein funktionale JDBC-Schicht für Scala. Ein Transactor[F] bildet die Brücke zwischen den reinen Programmen von Doobie und einer tatsächlichen Datenbankverbindung.
Ein Transactor weiß, wie eine JDBC-Connection erworben, Ihr Programm innerhalb einer Transaktion ausgeführt und Ressourcen sicher freigegeben werden.
Er ist durch einen Effekttyp F[_] wie cats.effect.IO parametrisiert.
import doobie._
import cats.effect.IO
val xa: Transactor[IO] = ???Das ConnectionIO-Programm
Doobie-Abfragen sind Werte vom Typ ConnectionIO[A]. Sie beschreiben eine Berechnung, die eine JDBC-Verbindung benötigt, aber noch nicht ausgeführt wird.
Sie erstellen diese Programme rein funktional und übergeben sie anschließend einem Transactor zur Ausführung. Die Datenbank wird erst berührt, wenn Sie das Programm ausführen.
import doobie.implicits._
val program: ConnectionIO[Int] =
sql"select 42".query[Int].uniqueDriverManagerTransactor
Der einfachste Transactor ist Transactor.fromDriverManager. Er öffnet für jede Transaktion mithilfe von JDBCs DriverManager eine vollständig neue Verbindung.
Er benötigt den Namen der Treiberklasse, die JDBC-URL, den Benutzernamen und das Passwort. Für Tests und Skripte ist er geeignet, aber er verfügt über keinen Connection-Pool.
val xa = Transactor.fromDriverManager[IO](
driver = "org.postgresql.Driver",
url = "jdbc:postgresql://localhost:5432/app",
user = "postgres",
password = "secret",
logHandler = None
)Ein Programm ausführen
Um ein ConnectionIO auszuführen, rufen Sie .transact(xa) auf. Das ergibt ein F[A], hier ein IO[A].
Der Transactor führt das Programm innerhalb einer Transaktion aus: Bei Erfolg führt er ein Commit durch, bei einem Fehler ein Rollback und gibt die Verbindung in beiden Fällen frei.
import doobie.implicits._
val result: IO[Int] =
sql"select 42".query[Int].unique.transact(xa)Pooling mit HikariCP
Für den produktiven Einsatz benötigen Sie einen Connection-Pool. Doobie liefert dafür HikariTransactor, das auf HikariCP basiert.
Es wird als Resource erstellt, sodass der Pool ordnungsgemäß heruntergefahren wird. Außerdem übergeben Sie einen Execution Context für blockierende JDBC-Operationen.
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
)Warum eine Resource?
Ein gepoolter Transactor besitzt langlebigen Zustand: offene Verbindungen und Hintergrund-Threads. Resource[F, A] garantiert, dass Erwerb und Freigabe auch bei Fehlern oder Abbruch zusammengehören.
Normalerweise erstellen Sie den Transactor einmal beim Start und verwenden ihn während der gesamten Lebensdauer der Anwendung wieder.
xaRes.use { xa =>
program.transact(xa)
}Der connectEC-Pool
HikariCP benötigt einen ExecutionContext, um auf Verbindungen aus dem Pool zu warten. Doobie stellt dafür ExecutionContexts.fixedThreadPool bereit, das selbst eine Resource ist.
Wenn Sie diesen Pool vom Compute-Pool getrennt halten, verhindern Sie, dass die blockierende Verbindungsbeschaffung CPU-intensive Arbeit ausbremst.
import doobie.util.ExecutionContexts
val poolRes =
for {
ec <- ExecutionContexts.fixedThreadPool[IO](8)
xa <- HikariTransactor.newHikariTransactor[IO](
"org.postgresql.Driver", url, user, pass, ec)
} yield xaEine vorhandene DataSource konfigurieren
Wenn Sie bereits über eine konfigurierte javax.sql.DataSource verfügen, etwa eine abgestimmte Hikari-Instanz, können Sie sie direkt mit Transactor.fromDataSource einbinden.
Das ist üblich, wenn ein Framework den Pool verwaltet und Doobie ihn lediglich verwenden soll.
val xa = Transactor.fromDataSource[IO](
dataSource = myDataSource,
connectEC = connectEC
)Die Verbindung einem Smoke-Test unterziehen
Ein einfacher Health-Check besteht darin, select 1 über den Transactor auszuführen. Wenn die Abfrage erfolgreich ist, funktionieren Treiber, URL und Zugangsdaten.
Das ist ein guter erster Schritt, bevor Sie echte Abfragen anbinden.
val check: IO[Int] =
sql"select 1".query[Int].unique.transact(xa)
// check.unsafeRunSync() == 1Interna des Transactors: Strategy
Ein Transactor wird aus Interpretern und einer Strategy aufgebaut. Die Strategy steuert, was rund um jede Transaktion geschieht: before, after, oops (bei einem Fehler) und always.
Die Standardstrategie deaktiviert Auto-Commit, führt nach Erfolg ein Commit durch, bei Fehlern ein Rollback und schließt die Verbindung immer.
import doobie.util.transactor.Strategy
val noCommit = xa.copy(
strategy0 = Strategy.default.copy(after = doobie.free.connection.unit)
)Logging und Observability
Doobie kann jedes Statement, seine Argumente und die Ausführungszeit protokollieren. Moderne Versionen verwenden pro Abfrage einen LogHandler[F] statt pro Transactor.
Das ist äußerst hilfreich, um langsame Abfragen zu erkennen und die Parameterbindung in Produktion zu überprüfen.
import doobie.util.log._
val handler: LogHandler[IO] = (ev: LogEvent) =>
IO.println(ev.sql)Kurze Überprüfung
Testen Sie Ihr Verständnis von Transactors.
Zusammenfassung
Ein Transactor[F] verbindet reine ConnectionIO-Programme mit einer tatsächlichen Datenbank. fromDriverManager eignet sich für Tests; HikariTransactor und fromDataSource eignen sich dank Pooling für den produktiven Einsatz.
Erstellen Sie gepoolte Transactors als Resource, führen Sie Programme mit .transact(xa) aus und überlassen Sie der Standard-Strategy Commit, Rollback und Bereinigung.
Häufig gestellte Fragen
Ist die Lektion „Mit einem Transactor verbinden“ kostenlos?
Ja — der vollständige Text von „Mit einem Transactor verbinden“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Scala for Backend Engineering & Functional Programming-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Mit einem Transactor verbinden“?
Richten Sie den Datenbankzugriff ein. Du übst Scala for Backend Engineering & Functional Programming mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Scala for Backend Engineering & Functional Programming zu starten?
Keine Vorkenntnisse erforderlich. Scala for Backend Engineering & Functional Programming auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „Mit einem Transactor verbinden“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Scala for Backend Engineering & Functional Programming-Lektion Code schreiben und ausführen?
Ja. Jede Scala for Backend Engineering & Functional Programming-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Mit einem Transactor verbinden
- Abfragen ausführen
- Einfügen und aktualisieren
- Transaktionen kombinieren