Skip to main content
O Spring Boot se conecta ao Postgres por meio do driver JDBC do PostgreSQL (pgjdbc) e de um pool de conexões HikariCP, e executa as migrações do Flyway na inicialização da aplicação. Neste guia, você cria uma tabela todos com uma migração do Flyway e atende a requisições de criação, leitura, atualização e exclusão por meio de um controller REST do Spring Data JPA. Todas as conexões usam TLS com verificação completa de certificados.

Pré-requisitos

  • JDK 17 ou superior, conforme exigido pelo Spring Boot 4. Este guia foi testado com Java 25, Spring Boot 4.1.1, pgjdbc 42.7.13, Hibernate 7.4.5, HikariCP 7.0.2 e Flyway 12.4.0.
  • Uma conta no ClickHouse Cloud
  • psql, para criar o banco de dados. Você também pode executar a instrução CREATE DATABASE no SQL Console.

Crie um serviço ClickHouse Managed Postgres

No console do ClickHouse Cloud, clique em New service e selecione Postgres. A instância fica pronta em poucos minutos. Para um passo a passo, consulte o guia de início rápido.

Obtenha os detalhes de conexão

Clique em Connect na barra lateral esquerda do seu serviço. O modal exibe seu nome de usuário, senha, servidor e porta, além de uma chave de alternância Directly / via PgBouncer. Com Directly selecionado, ative Use SSL e abra a aba jdbc. Ela exibe uma URL JDBC que você poderá usar no Spring Boot depois de fazer duas alterações, descritas em Configure a conexão: o nome do banco de dados e o nome do arquivo do certificado da CA.
A URL JDBC não contém o nome de usuário nem a senha. O Spring Boot os lê de propriedades separadas. Este guia se conecta diretamente ao Postgres na porta 5432. Uma aplicação Spring Boot é um processo de longa duração que mantém seu próprio pool do HikariCP, com 10 conexões por padrão, então não precisa de um segundo pooler na frente do Postgres. Garanta que o número de instâncias da aplicação multiplicado pelo tamanho do pool fique abaixo do max_connections do serviço. Se você executar muitas instâncias, consulte Usar o PgBouncer. No modal, clique em Download CA certificate. Você também pode baixá-lo em Settings → CA Certificate. O certificado é único para a sua instância, permitindo que o driver o use para verificar se está se comunicando com o seu servidor.

Configure o projeto

Gere um projeto Maven com o Spring Initializr, incluindo as dependências Spring Web, Spring Data JPA, Flyway Migration e PostgreSQL Driver:
Vai adicionar a uma aplicação existente?Pule o comando curl. No seu pom.xml, adicione as dependências spring-boot-starter-data-jpa, spring-boot-starter-flyway e org.flywaydb:flyway-database-postgresql, além de org.postgresql:postgresql com escopo runtime, e remova com.h2database:h2 se a sua aplicação usar H2. Em seguida, siga para Configurar a conexão.

Configure a conexão

Mova o certificado da CA que você baixou para o diretório do projeto e renomeie-o para ca-certificate.pem. Crie um banco de dados para a aplicação. Substitua <PASSWORD> e o host pelos valores exibidos no modal Connect:
Substitua o conteúdo de src/main/resources/application.properties pelo seguinte. Em uma aplicação existente, adicione as linhas spring.datasource e spring.jpa e remova as demais configurações spring.datasource, como uma URL do H2. A URL é a mesma da aba jdbc, mas com o banco de dados alterado para guide_spring e o sslrootcert apontando para o arquivo renomeado:
src/main/resources/application.properties
O pgjdbc lê sslmode=verify-full e sslrootcert da URL. Ele carrega todos os certificados do arquivo da CA e verifica tanto a cadeia de certificados quanto o hostname, portanto você não precisa de nenhum código TLS adicional. O Spring Boot lê a senha da variável de ambiente DATABASE_PASSWORD, de modo que ela não fica no arquivo. As demais configurações:
  • ddl-auto=validate faz com que o Hibernate verifique, na inicialização, se suas entidades correspondem às tabelas criadas pelo Flyway. O Hibernate não altera o schema.
  • open-in-view=false devolve cada conexão ao pool assim que sua transação termina, em vez de mantê-la até que a resposta HTTP seja gravada.
Um caminho relativo em sslrootcert é resolvido a partir do diretório de trabalho da JVM. ./mvnw spring-boot:run inicia a aplicação no diretório do projeto, então ca-certificate.pem funciona nesse caso. Ao executar o JAR empacotado em outro local, use um caminho absoluto. O pgjdbc não expande ~.Se você copiar a URL com Use SSL desativado, ela não terá sslmode, e o pgjdbc usará prefer: ele criptografa a conexão, mas não verifica o servidor. Com a CA errada, a conexão falha com PKIX path building failed. Se o arquivo não existir, ela falha com Could not open SSL root certificate file. Se o host não corresponder ao certificado, por exemplo ao conectar por endereço IP, ela falha com The hostname ... could not be verified by hostnameverifier PgjdbcHostnameVerifier.

Crie a tabela com o Flyway

O Flyway executa os arquivos SQL em src/main/resources/db/migration por ordem de versão quando a aplicação é iniciada, antes que o Hibernate valide o schema. Crie o arquivo src/main/resources/db/migration/V1__create_todos.sql:
src/main/resources/db/migration/V1__create_todos.sql
O Flyway registra cada arquivo aplicado na tabela flyway_schema_history e, nas inicializações seguintes, executa apenas os arquivos novos. Para alterar o schema, adicione um novo arquivo, como V2__add_due_date.sql, em vez de editar um que já tenha sido executado.
Uma aplicação que usava H2 normalmente deixava o Hibernate criar as tabelas, porque o padrão de ddl-auto é create-drop para bancos de dados embutidos. No Postgres, o padrão é none; portanto, adicione uma migração que crie as tabelas que você já tem. Um @Id com um @GeneratedValue simples também exige uma sequência com o nome da entidade, como employee_seq para Employee, com incremento de 50, o tamanho de alocação padrão do Hibernate. Caso contrário, a inicialização falha com Schema validation: missing sequence [employee_seq] ou, se a sequência tiver incremento de 1, com The increment size of the [employee_seq] sequence is set to [50] in the entity mapping but the mapped database sequence increment size is [1]:

Consultar o banco de dados

Crie a entidade em src/main/java/com/example/todos/Todo.java. O Spring Boot mapeia o campo createdAt para a coluna created_at:
src/main/java/com/example/todos/Todo.java
Crie um repositório Spring Data em src/main/java/com/example/todos/TodoRepository.java. O Spring Data implementa a interface em tempo de execução:
src/main/java/com/example/todos/TodoRepository.java
Crie um controller REST em src/main/java/com/example/todos/TodoController.java, com uma chamada ao repositório por rota:
src/main/java/com/example/todos/TodoController.java
Cada chamada ao repositório é executada em sua própria transação, usando uma conexão do pool do HikariCP. Para agrupar várias chamadas em uma única transação, coloque-as em um método anotado com @Transactional.

Executar e verificar

Defina a senha e inicie a aplicação:
Na primeira inicialização, o Flyway aplica a migração antes de o servidor web iniciar. O log inclui as linhas abaixo, mostradas aqui sem os timestamps e os nomes das threads:
Em um segundo terminal, crie duas tarefas, marque a primeira como concluída e exclua a segunda:
As requisições POST retornam as novas linhas, e a requisição PATCH retorna a linha atualizada. O -w '\n' adiciona uma quebra de linha após cada resposta:
Abra http://localhost:3113/todos no navegador para listar as tarefas pendentes. A resposta será semelhante a esta:
Para confirmar que as conexões da aplicação usam TLS, consulte pg_stat_ssl com a aplicação em execução:
As 10 conexões correspondem ao pool do HikariCP. Encerre a aplicação com Ctrl+C. Para ver os dados no console, abra o SQL Console na barra lateral esquerda do seu serviço, expanda guide_spring e depois public e clique na tabela todos. Ao lado dela, a tabela flyway_schema_history armazena o histórico de migrações. A tabela todos contém a linha restante:

Use o PgBouncer

Quando o conjunto de instâncias da aplicação se aproximar do limite de conexões do Postgres, conecte a aplicação por meio do PgBouncer incluído, na porta 6432, e mantenha o Flyway na conexão direta. Em application.properties, altere a porta em spring.datasource.url para 6432 e adicione as linhas spring.flyway logo abaixo:
src/main/resources/application.properties
Quando spring.flyway.url está definido, o Flyway abre sua própria conexão e não usa o nome de usuário e a senha de spring.datasource; portanto, defina também spring.flyway.user e spring.flyway.password. O mesmo certificado de CA serve para as duas portas. O PgBouncer opera no modo de pooling de transações, então cada transação pode ser executada em uma conexão Postgres diferente. Com o Spring Boot:
  • Prepared statements funcionam com as configurações padrão do driver, então você não precisa de prepareThreshold=0. A partir da quinta execução de uma instrução em uma conexão (prepareThreshold), o pgjdbc passa a usar um prepared statement nomeado do lado do servidor. Ele libera as instruções com uma mensagem Close no nível do protocolo, que o PgBouncer incluído sabe tratar.
  • pgjdbc 42.7.5 ou posterior é obrigatório. Versões mais antigas enviam o parâmetro de inicialização extra_float_digits, e o PgBouncer rejeita a conexão com FATAL: unsupported startup parameter: extra_float_digits. O Spring Boot 4 já inclui um pgjdbc mais recente. Em versões mais antigas do Spring Boot, defina <postgresql.version>42.7.13</postgresql.version> na seção <properties> do pom.xml.
  • As configurações de sessão não persistem. Instruções SET e Connection.setSchema, usado pela propriedade spring.datasource.hikari.schema do HikariCP, se aplicam apenas à conexão Postgres que as executa e podem vazar para outros clientes. Os parâmetros de URL currentSchema e options falham com FATAL: unsupported startup parameter. Use nomes de tabela qualificados com o schema ou SET LOCAL dentro de uma transação.
  • Flyway funciona através do PgBouncer por padrão, pois adquire um advisory lock no nível da transação. Migrações que executam CREATE INDEX CONCURRENTLY exigem spring.flyway.postgresql.transactional-lock=false, o que faz o Flyway passar a usar um bloqueio no nível da sessão. Através do PgBouncer, esse bloqueio falha com Unable to release PostgreSQL advisory lock e continua retido em uma conexão do pool; portanto, use a conexão direta para o Flyway.
  • Tamanho do pool: cada conexão do HikariCP é uma conexão de cliente de baixo custo com o PgBouncer. O PgBouncer limita as conexões Postgres que abre para cada banco de dados e usuário (default_pool_size), independentemente de quantas conexões de cliente as instâncias da sua aplicação abram. Transações acima desse limite aguardam no PgBouncer por até query_wait_timeout (120 segundos por padrão), em vez de falharem no HikariCP. Um pool maior no HikariCP só aumenta a concorrência até esse limite, então o padrão de 10 por instância é um bom ponto de partida. Consulte Limites de conexão do PgBouncer e do Postgres.
O pg_stat_ssl mostra a conexão entre o PgBouncer e o Postgres, portanto a consulta de TLS em Executar e verificar não exibe as conexões da aplicação feitas através do PgBouncer. Ainda assim, a conexão da aplicação com o PgBouncer é verificada: um certificado de CA incorreto falha da mesma forma.

Próximos passos