Skip to main content
Spring Boot se conecta a Postgres mediante el controlador JDBC de PostgreSQL (pgjdbc) y un grupo de conexiones HikariCP, y ejecuta las migraciones de Flyway al iniciar la aplicación. En esta guía, creará una tabla todos con una migración de Flyway y atenderá solicitudes de creación, lectura, actualización y eliminación desde un controlador REST de Spring Data JPA. Todas las conexiones usan TLS con verificación completa del certificado.

Requisitos previos

  • JDK 17 o posterior, como exige Spring Boot 4. Esta guía se probó con Java 25, Spring Boot 4.1.1, pgjdbc 42.7.13, Hibernate 7.4.5, HikariCP 7.0.2 y Flyway 12.4.0.
  • Una cuenta de ClickHouse Cloud
  • psql, para crear la base de datos. También puede ejecutar la sentencia CREATE DATABASE en la consola SQL.

Crear un servicio de ClickHouse Managed Postgres

En la consola de ClickHouse Cloud, haga clic en New service y seleccione Postgres. La instancia estará lista en unos minutos. Consulte la guía de inicio rápido para ver el proceso paso a paso.

Obtener los datos de conexión

Haga clic en Conectar en la barra lateral izquierda de su servicio. El cuadro de diálogo muestra su nombre de usuario, contraseña, servidor y puerto, e incluye un toggle Directly / via PgBouncer. Con Directly seleccionado, active Use SSL y abra la pestaña jdbc. Allí verá una URL JDBC que podrá usar en Spring Boot tras realizar dos cambios, que se describen en Configurar la conexión: el nombre de la base de datos y el nombre del archivo del certificado de la CA.
La URL de JDBC no incluye el nombre de usuario ni la contraseña. Spring Boot los lee de propiedades independientes. Esta guía se conecta directamente a Postgres en el puerto 5432. Una aplicación Spring Boot es un proceso de larga duración que mantiene su propio grupo de conexiones de HikariCP (10 conexiones de forma predeterminada), por lo que no necesita un segundo pooler delante de Postgres. Asegúrese de que el número de instancias de la aplicación multiplicado por el tamaño del grupo se mantenga por debajo del valor de max_connections del servicio. Si ejecuta muchas instancias, consulte Usar PgBouncer. En el cuadro de diálogo, haga clic en Download CA certificate. También puede descargarlo desde Settings → CA Certificate. El certificado es exclusivo de su instancia, de modo que el controlador puede usarlo para verificar que se está comunicando con su servidor.

Configurar el proyecto

Genere un proyecto Maven con Spring Initializr que incluya las dependencias Spring Web, Spring Data JPA, Flyway Migration y PostgreSQL Driver:
¿Va a añadirlo a una aplicación existente?Omita el comando curl. En su pom.xml, añada las dependencias spring-boot-starter-data-jpa, spring-boot-starter-flyway y org.flywaydb:flyway-database-postgresql, así como org.postgresql:postgresql con alcance runtime, y elimine com.h2database:h2 si su aplicación usa H2. Después, continúe con Configurar la conexión.

Configurar la conexión

Mueva el certificado de CA que descargó al directorio del proyecto y cámbiele el nombre a ca-certificate.pem. Cree una base de datos para la aplicación. Sustituya <PASSWORD> y el host por los valores del cuadro de diálogo Conectar:
Reemplace el contenido de src/main/resources/application.properties por lo siguiente. En una aplicación existente, agregue las líneas spring.datasource y spring.jpa y elimine cualquier otra configuración de spring.datasource, como una URL de H2. La URL es la de la pestaña jdbc, cambiando la base de datos a guide_spring y sslrootcert al archivo renombrado:
src/main/resources/application.properties
pgjdbc lee sslmode=verify-full y sslrootcert de la URL. Carga todos los certificados del archivo de la CA y verifica tanto la cadena de certificados como el nombre del host, por lo que no necesita código TLS adicional. Spring Boot lee la contraseña de la variable de entorno DATABASE_PASSWORD, de modo que no queda expuesta en el archivo. El resto de la configuración:
  • ddl-auto=validate hace que Hibernate compruebe durante el inicio que sus entidades coinciden con las tablas que crea Flyway. Hibernate no modifica el esquema.
  • open-in-view=false devuelve cada conexión al grupo en cuanto finaliza su transacción, en lugar de retenerla hasta que se escribe la respuesta HTTP.
Una ruta relativa en sslrootcert se resuelve con respecto al directorio de trabajo de la JVM. ./mvnw spring-boot:run inicia la aplicación en el directorio del proyecto, así que ca-certificate.pem funciona en ese caso. Si ejecuta el JAR empaquetado desde otra ubicación, use una ruta absoluta. pgjdbc no expande ~.Si copia la URL con Use SSL desactivado, esta no incluye sslmode y pgjdbc recurre a prefer: cifra la conexión, pero no verifica el servidor. Si la CA es incorrecta, la conexión falla con PKIX path building failed. Si falta el archivo, falla con Could not open SSL root certificate file. Si el host no coincide con el certificado (por ejemplo, al conectarse mediante una dirección IP), falla con The hostname ... could not be verified by hostnameverifier PgjdbcHostnameVerifier.

Crear la tabla con Flyway

Flyway ejecuta los archivos SQL de src/main/resources/db/migration por orden de versión al iniciarse la aplicación, antes de que Hibernate valide el esquema. Cree src/main/resources/db/migration/V1__create_todos.sql:
src/main/resources/db/migration/V1__create_todos.sql
Flyway registra cada archivo aplicado en la tabla flyway_schema_history y, en los inicios posteriores, solo ejecuta los archivos nuevos. Para modificar el esquema, agregue un archivo nuevo, como V2__add_due_date.sql, en lugar de editar uno que ya se haya ejecutado.
Una aplicación que usaba H2 normalmente dejaba que Hibernate creara sus tablas, ya que ddl-auto toma por defecto el valor create-drop en las bases de datos embebidas. En Postgres, el valor predeterminado es none, por lo que debe agregar una migración que cree sus tablas existentes. Además, un @Id con un @GeneratedValue simple requiere una secuencia con el nombre de la entidad, como employee_seq para Employee, que se incremente en 50, el tamaño de asignación predeterminado de Hibernate. De lo contrario, el inicio falla con Schema validation: missing sequence [employee_seq] o, si la secuencia se incrementa en 1, con 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 la base de datos

Cree la entidad en src/main/java/com/example/todos/Todo.java. Spring Boot mapea el campo createdAt a la columna created_at:
src/main/java/com/example/todos/Todo.java
Cree un repositorio de Spring Data en src/main/java/com/example/todos/TodoRepository.java. Spring Data implementa la interfaz en tiempo de ejecución:
src/main/java/com/example/todos/TodoRepository.java
Cree un controlador REST en src/main/java/com/example/todos/TodoController.java, con una llamada al repositorio por ruta:
src/main/java/com/example/todos/TodoController.java
Cada llamada al repositorio se ejecuta en su propia transacción, usando una conexión del grupo de HikariCP. Para agrupar varias llamadas en una sola transacción, inclúyalas en un método anotado con @Transactional.

Ejecutar y verificar

Configure la contraseña e inicie la aplicación:
En el primer arranque, Flyway aplica la migración antes de que se inicie el servidor web. El log incluye las siguientes líneas, que se muestran aquí sin marcas de tiempo ni nombres de thread:
En una segunda terminal, cree dos tareas, marque la primera como completada y elimine la segunda:
Las solicitudes POST devuelven las filas nuevas y la solicitud PATCH devuelve la fila actualizada. -w '\n' añade un salto de línea después de cada respuesta:
Abra http://localhost:3113/todos en su navegador para ver la lista de tareas pendientes. La respuesta será similar a la siguiente:
Para confirmar que las conexiones de la aplicación usan TLS, consulte pg_stat_ssl mientras la aplicación está en ejecución:
Las 10 conexiones corresponden al grupo de HikariCP. Detenga la aplicación con Ctrl+C. Para ver los datos en la consola, abra consola SQL en la barra lateral izquierda de su servicio, expanda guide_spring y después public, y haga clic en la tabla todos. La tabla flyway_schema_history, que aparece junto a ella, almacena el historial de migraciones. La tabla todos contiene la fila restante:

Usar PgBouncer

Cuando el conjunto de instancias de la aplicación se acerque al límite de conexiones de Postgres, conecte la aplicación a través del PgBouncer incluido, en el puerto 6432, y mantenga Flyway en la conexión directa. En application.properties, cambie el puerto de spring.datasource.url a 6432 y agregue debajo las líneas spring.flyway:
src/main/resources/application.properties
Cuando se establece spring.flyway.url, Flyway abre su propia conexión y no utiliza el nombre de usuario ni la contraseña de spring.datasource, por lo que también debe establecer spring.flyway.user y spring.flyway.password. El mismo certificado de CA sirve para ambos puertos. PgBouncer se ejecuta en modo de agrupación por transacción, por lo que cada transacción puede ejecutarse en una conexión de Postgres distinta. Con Spring Boot:
  • Las sentencias preparadas funcionan con la configuración predeterminada del controlador, así que no necesita prepareThreshold=0. A partir de la quinta ejecución de una sentencia en una misma conexión (prepareThreshold), pgjdbc utiliza una sentencia preparada con nombre del lado del servidor. Las sentencias se liberan mediante un mensaje Close a nivel de protocolo, que el PgBouncer incluido admite.
  • Se requiere pgjdbc 42.7.5 o posterior. Las versiones anteriores envían el parámetro de inicio extra_float_digits, y PgBouncer rechaza la conexión con FATAL: unsupported startup parameter: extra_float_digits. Spring Boot 4 incluye una versión más reciente de pgjdbc. En versiones anteriores de Spring Boot, establezca <postgresql.version>42.7.13</postgresql.version> en la sección <properties> de pom.xml.
  • La configuración de sesión no persiste. Las sentencias SET y Connection.setSchema (que utiliza la propiedad spring.datasource.hikari.schema de HikariCP) solo se aplican a la conexión de Postgres que las ejecuta y pueden filtrarse a otros clientes. Los parámetros de URL currentSchema y options fallan con FATAL: unsupported startup parameter. Utilice nombres de tabla calificados con el esquema o SET LOCAL dentro de una transacción.
  • Flyway funciona a través de PgBouncer de forma predeterminada, ya que adquiere un bloqueo consultivo a nivel de transacción. Las migraciones que ejecutan CREATE INDEX CONCURRENTLY requieren spring.flyway.postgresql.transactional-lock=false, que hace que Flyway use un bloqueo a nivel de sesión. A través de PgBouncer, ese bloqueo falla con Unable to release PostgreSQL advisory lock y queda retenido en una conexión agrupada, por lo que debe usar la conexión directa para Flyway.
  • Tamaño del grupo: cada conexión de HikariCP es una conexión de cliente a PgBouncer con un coste mínimo. PgBouncer limita las conexiones de Postgres que abre para cada base de datos y usuario (default_pool_size), independientemente de cuántas conexiones de cliente abran las instancias de su aplicación. Las transacciones que superan ese límite esperan en PgBouncer hasta query_wait_timeout (120 segundos de forma predeterminada) en lugar de fallar en HikariCP. Ampliar el grupo de HikariCP solo aumenta la concurrencia hasta ese límite, por lo que el valor predeterminado de 10 por instancia es un buen punto de partida. Consulte Límites de conexión de PgBouncer y Postgres.
pg_stat_ssl informa sobre la conexión entre PgBouncer y Postgres, por lo que la consulta de TLS de Ejecutar y verificar no muestra las conexiones de la aplicación a través de PgBouncer. Aun así, la conexión de la aplicación a PgBouncer sí se verifica: con un certificado de CA incorrecto, falla igualmente.

Próximos pasos