Conectando com um transator
Configure o acesso ao banco de dados.
Conectando com um transator é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que é um Transactor?
O Doobie é uma camada JDBC puramente funcional para Scala. Um Transactor[F] é a ponte entre os programas puros do Doobie e uma conexão real com o banco de dados.
Um Transactor sabe como adquirir uma Connection JDBC, executar seu programa dentro de uma transação e liberar os recursos com segurança.
Ele é parametrizado por um tipo de efeito F[_], como cats.effect.IO.
import doobie._
import cats.effect.IO
val xa: Transactor[IO] = ???O programa ConnectionIO
As consultas do Doobie são valores do tipo ConnectionIO[A]. Elas descrevem uma computação que precisa de uma conexão JDBC, mas ainda não é executada.
Você constrói esses programas de forma pura e depois os entrega a um Transactor para executá-los. Nada acessa o banco de dados até que você os execute.
import doobie.implicits._
val program: ConnectionIO[Int] =
sql"select 42".query[Int].uniqueDriverManagerTransactor
O Transactor mais simples é Transactor.fromDriverManager. Ele abre uma conexão completamente nova para cada transação usando o DriverManager do JDBC.
Ele precisa do nome da classe do driver, da URL JDBC, do nome de usuário e da senha. É adequado para testes e scripts, mas não possui um conjunto de conexões.
val xa = Transactor.fromDriverManager[IO](
driver = "org.postgresql.Driver",
url = "jdbc:postgresql://localhost:5432/app",
user = "postgres",
password = "secret",
logHandler = None
)Executando um programa
Para executar um ConnectionIO, você chama .transact(xa). Isso produz um F[A], neste caso, um IO[A].
O Transactor envolve o programa em uma transação: confirma em caso de sucesso e desfaz em caso de falha, liberando a conexão de qualquer forma.
import doobie.implicits._
val result: IO[Int] =
sql"select 42".query[Int].unique.transact(xa)Agrupamento com HikariCP
Em produção, você precisa de um conjunto de conexões. O Doobie inclui o HikariTransactor, desenvolvido sobre o HikariCP.
Ele é criado como um Resource, para que o conjunto seja encerrado corretamente. Você também passa um contexto de execução para as operações JDBC bloqueantes.
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
)Por que um Resource?
Um Transactor com agrupamento possui estado de longa duração: conexões abertas e threads em segundo plano. Resource[F, A] garante que a aquisição e a liberação sejam pareadas, mesmo em caso de erros ou cancelamento.
Normalmente, você constrói o Transactor uma vez na inicialização e o reutiliza durante todo o ciclo de vida da aplicação.
xaRes.use { xa =>
program.transact(xa)
}O conjunto connectEC
O HikariCP precisa de um ExecutionContext para aguardar conexões do conjunto. O Doobie fornece ExecutionContexts.fixedThreadPool para isso, que por sua vez é um Resource.
Manter esse conjunto separado do conjunto de computação impede que a aquisição bloqueante de conexões prive de recursos o trabalho limitado pela 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 xaConfigurando um DataSource existente
Se você já tiver um javax.sql.DataSource configurado, por exemplo, uma instância ajustada do Hikari, envolva-o diretamente com Transactor.fromDataSource.
Isso é comum quando uma estrutura gerencia o conjunto e você quer apenas que o Doobie o utilize.
val xa = Transactor.fromDataSource[IO](
dataSource = myDataSource,
connectEC = connectEC
)Testando rapidamente a conexão
Uma verificação de integridade simples consiste em executar select 1 por meio do Transactor. Se houver retorno, o driver, a URL e as credenciais estarão funcionando.
Este é um bom primeiro passo antes de configurar consultas reais.
val check: IO[Int] =
sql"select 1".query[Int].unique.transact(xa)
// check.unsafeRunSync() == 1Internos do Transactor: Strategy
Um Transactor é construído a partir de interpretadores e de uma Strategy. A Strategy controla o que acontece em torno de cada transação: before, after, oops (em caso de erro) e always.
A estratégia padrão desativa a confirmação automática, confirma após o sucesso, desfaz em caso de erro e sempre fecha a conexão.
import doobie.util.transactor.Strategy
val noCommit = xa.copy(
strategy0 = Strategy.default.copy(after = doobie.free.connection.unit)
)Registro e observabilidade
O Doobie pode registrar cada instrução, seus argumentos e o tempo de execução. As versões modernas associam um LogHandler[F] a cada consulta, em vez de a cada Transactor.
Isso é extremamente útil para identificar consultas lentas e verificar a associação de parâmetros em produção.
import doobie.util.log._
val handler: LogHandler[IO] = (ev: LogEvent) =>
IO.println(ev.sql)Verificação rápida
Teste sua compreensão sobre Transactors.
Recapitulação
Um Transactor[F] conecta programas puros ConnectionIO a um banco de dados real. fromDriverManager é adequado para testes; HikariTransactor e fromDataSource são adequados para produção por meio de agrupamento.
Construa Transactors agrupados como um Resource, execute programas com .transact(xa) e deixe a Strategy padrão cuidar da confirmação, do desfazimento e da limpeza.
Perguntas Frequentes
A aula “Conectando com um transator” é grátis?
Sim — o texto completo de “Conectando com um transator” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que vou aprender em “Conectando com um transator”?
Configure o acesso ao banco de dados. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Conectando com um transator”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Conectando com um transator
- Executando consultas
- Inserções e atualizações
- Compondo transações