Connettersi con un transactor
Configuri l'accesso al database.
Connettersi con un transactor è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
Che cos’è un Transactor?
Doobie è un layer JDBC funzionale puro per Scala. Un Transactor[F] fa da ponte tra i programmi puri di Doobie e una connessione reale al database.
Un Transactor sa come acquisire una Connection JDBC, eseguire il programma all’interno di una transazione e rilasciare le risorse in sicurezza.
È parametrizzato da un tipo di effetto F[_], come cats.effect.IO.
import doobie._
import cats.effect.IO
val xa: Transactor[IO] = ???Il programma ConnectionIO
Le query Doobie sono valori di tipo ConnectionIO[A]. Descrivono un calcolo che richiede una connessione JDBC, ma non lo eseguono ancora.
Si costruiscono questi programmi in modo puro, poi li si passa a un Transactor per eseguirli. Il database non viene toccato finché non si avvia l’esecuzione.
import doobie.implicits._
val program: ConnectionIO[Int] =
sql"select 42".query[Int].uniqueDriverManagerTransactor
Il Transactor più semplice è Transactor.fromDriverManager. Apre una connessione completamente nuova per ogni transazione usando il DriverManager di JDBC.
Richiede il nome della classe del driver, l’URL JDBC, il nome utente e la password. È adatto a test e script, ma non dispone di connection pooling.
val xa = Transactor.fromDriverManager[IO](
driver = "org.postgresql.Driver",
url = "jdbc:postgresql://localhost:5432/app",
user = "postgres",
password = "secret",
logHandler = None
)Esecuzione di un programma
Per eseguire un ConnectionIO si chiama .transact(xa). Si ottiene così un F[A], in questo caso un IO[A].
Il Transactor racchiude il programma in una transazione: esegue il commit in caso di successo e il rollback in caso di errore, rilasciando comunque la connessione.
import doobie.implicits._
val result: IO[Int] =
sql"select 42".query[Int].unique.transact(xa)Pooling con HikariCP
In produzione è consigliabile usare un pool di connessioni. Doobie include HikariTransactor, basato su HikariCP.
Viene creato come una Resource, così il pool viene arrestato correttamente. È inoltre necessario passare un execution context per le operazioni JDBC bloccanti.
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
)Perché una Resource?
Un Transactor con pooling gestisce uno stato di lunga durata: connessioni aperte e thread in background. Resource[F, A] garantisce che acquisizione e rilascio siano sempre associati, anche in caso di errori o cancellazione.
In genere si costruisce il Transactor una sola volta all’avvio e lo si riutilizza per tutta la vita dell’applicazione.
xaRes.use { xa =>
program.transact(xa)
}Il pool connectEC
HikariCP ha bisogno di un ExecutionContext per attendere le connessioni del pool. Doobie fornisce ExecutionContexts.fixedThreadPool a questo scopo, anch’esso come Resource.
Mantenere questo pool separato da quello per i calcoli impedisce che l’acquisizione bloccante delle connessioni esaurisca le risorse destinate al lavoro legato alla CPU.
import doobie.util.ExecutionContexts
val poolRes =
for {
ec <- ExecutionContexts.fixedThreadPool[IO](8)
xa <- HikariTransactor.newHikariTransactor[IO](
"org.postgresql.Driver", url, user, pass, ec)
} yield xaConfigurazione di un DataSource esistente
Se dispone già di un javax.sql.DataSource configurato (ad esempio un’istanza Hikari ottimizzata), lo avvolga direttamente con Transactor.fromDataSource.
È una soluzione comune quando un framework gestisce il pool e si desidera soltanto utilizzarlo con Doobie.
val xa = Transactor.fromDataSource[IO](
dataSource = myDataSource,
connectEC = connectEC
)Smoke test della connessione
Un semplice controllo di salute consiste nell’eseguire select 1 tramite il Transactor. Se la query restituisce un risultato, driver, URL e credenziali funzionano correttamente.
È un buon primo passo prima di collegare query reali.
val check: IO[Int] =
sql"select 1".query[Int].unique.transact(xa)
// check.unsafeRunSync() == 1Internals del Transactor: Strategy
Un Transactor è costruito a partire da interpreti e da una Strategy. La Strategy controlla ciò che accade intorno a ogni transazione: before, after, oops (in caso di errore) e always.
La strategia predefinita disattiva l’auto-commit, esegue il commit dopo il successo, il rollback in caso di errore e chiude sempre la connessione.
import doobie.util.transactor.Strategy
val noCommit = xa.copy(
strategy0 = Strategy.default.copy(after = doobie.free.connection.unit)
)Logging e osservabilità
Doobie può registrare ogni statement, i relativi argomenti e i tempi di esecuzione. Le versioni moderne associano un LogHandler[F] a ogni query anziché a ogni Transactor.
È prezioso per individuare query lente e verificare il binding dei parametri in produzione.
import doobie.util.log._
val handler: LogHandler[IO] = (ev: LogEvent) =>
IO.println(ev.sql)Verifica rapida
Verifichi la Sua comprensione dei Transactor.
Riepilogo
Un Transactor[F] collega i programmi puri ConnectionIO a un database reale. fromDriverManager è adatto ai test; HikariTransactor e fromDataSource sono adatti alla produzione grazie al pooling.
Costruisca i Transactor con pooling come Resource, esegua i programmi con .transact(xa) e lasci che la Strategy predefinita gestisca commit, rollback e pulizia.
Impara Scala con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 39
- Lezioni
- 143
Domande Frequenti
La lezione «Connettersi con un transactor» è gratuita?
Sì — il testo completo di «Connettersi con un transactor» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
Cosa imparerò in «Connettersi con un transactor»?
Configuri l'accesso al database. Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?
Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Connettersi con un transactor»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?
Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Connettersi con un transactor
- Eseguire query
- Inserimenti e aggiornamenti
- Comporre transazioni