0Pricing
Scala for Backend Engineering & Functional Programming · Aula

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].unique

DriverManagerTransactor

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 xa

Configurando 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() == 1

Internos 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

  1. Conectando com um transator
  2. Executando consultas
  3. Inserções e atualizações
  4. Compondo transações
← Voltar para Scala for Backend Engineering & Functional Programming