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çãoCREATE DATABASEno 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.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:Configure a conexão
Mova o certificado da CA que você baixou para o diretório do projeto e renomeie-o paraca-certificate.pem.
Crie um banco de dados para a aplicação. Substitua <PASSWORD> e o host pelos valores exibidos no modal Connect:
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
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=validatefaz 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=falsedevolve 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 emsrc/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
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 emsrc/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
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
src/main/java/com/example/todos/TodoController.java, com uma chamada ao repositório por rota:
src/main/java/com/example/todos/TodoController.java
@Transactional.
Executar e verificar
Defina a senha e inicie a aplicação: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:
pg_stat_ssl com a aplicação em execução:
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 porta6432, 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
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 mensagemCloseno 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 comFATAL: 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>dopom.xml. - As configurações de sessão não persistem. Instruções
SETeConnection.setSchema, usado pela propriedadespring.datasource.hikari.schemado HikariCP, se aplicam apenas à conexão Postgres que as executa e podem vazar para outros clientes. Os parâmetros de URLcurrentSchemaeoptionsfalham comFATAL: unsupported startup parameter. Use nomes de tabela qualificados com o schema ouSET LOCALdentro 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 CONCURRENTLYexigemspring.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 comUnable to release PostgreSQL advisory locke 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.
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
- Conexão: strings de conexão, PgBouncer e TLS
- Configurações: parâmetros do Postgres e do PgBouncer, como
max_connections - Réplicas de leitura: envie consultas read-only para uma réplica
- Segurança: listas de acesso por IP e rede privada