PostgreSQL Integration
PostgreSQL is a powerful, standards-compliant open-source database with rich data types and strong transactional guarantees. Spring Boot connects to it the same way it connects to any JDBC database: add the driver, configure spring.datasource.*, and your Spring Data JPA repositories work unchanged.
Adding the dependency
The PostgreSQL JDBC driver lives at org.postgresql:postgresql. Add it as a runtime dependency next to the JPA starter.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
Note: With
spring-boot-starter-parent, the driver version is managed, so omit the<version>. Spring Boot 3.5 pulls in a current 42.x driver.
Datasource configuration
Point the datasource at your Postgres server. The default port is 5432.
spring:
datasource:
url: jdbc:postgresql://localhost:5432/shopdb
username: shop
password: secret
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: validate
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
show-sql: true
Hibernate 6 auto-detects the dialect from the connection, so PostgreSQLDialect is usually optional. The ddl-auto values behave exactly as in the MySQL guide: use validate in production.
Working with schemas
Postgres organizes objects into schemas (namespaces within a database). The default schema is public. You can target a specific schema in two ways.
spring:
datasource:
url: jdbc:postgresql://localhost:5432/shopdb?currentSchema=sales
Or set the default schema for Hibernate’s generated SQL:
spring:
jpa:
properties:
hibernate:
default_schema: sales
You can also pin a schema per entity with @Table(schema = "sales", name = "products").
Running PostgreSQL in Docker
Spin up a local server with the official image, matching the credentials in your config.
docker run --name pg-shop \
-e POSTGRES_DB=shopdb \
-e POSTGRES_USER=shop \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
-d postgres:16
Confirm connectivity:
docker exec -it pg-shop psql -U shop -d shopdb -c "\l"
Output:
Name | Owner | Encoding | Collate
----------+-------+----------+-------------
shopdb | shop | UTF8 | en_US.utf8
Postgres-specific types: jsonb
One of Postgres’s standout features is the jsonb column type, which stores JSON in a binary, indexable form. With Hibernate 6 you can map a Java field directly to jsonb using the built-in @JdbcTypeCode.
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@JdbcTypeCode(SqlTypes.JSON)
@Column(columnDefinition = "jsonb")
private Map<String, Object> attributes;
// constructors, getters, setters
}
Hibernate serializes the Map to JSON on write and deserializes on read. The generated column is true jsonb, so you can query it with Postgres JSON operators in a native query.
@Query(value = "SELECT * FROM products WHERE attributes ->> 'color' = :color",
nativeQuery = true)
List<Product> findByColor(@Param("color") String color);
Tip:
jsonbsupports GIN indexes, which make containment queries (@>) fast even on large tables. Use it for flexible, semi-structured attributes, but keep relational columns for fields you filter or join on frequently.
Other useful Postgres types
| Java type | Postgres column | Notes |
|---|---|---|
UUID | uuid | Native UUID storage, ideal for IDs |
Map/POJO + @JdbcTypeCode(JSON) | jsonb | Indexable JSON documents |
String[] / List | text[] | Native array columns |
Instant | timestamptz | Timezone-aware timestamps |
Best Practices
- Keep credentials out of source control; inject them via environment variables or a secrets manager.
- Use
ddl-auto: validatewith Flyway or Liquibase migrations in production. - Prefer
timestamptzfor timestamps so values are stored unambiguously in UTC. - Index
jsonbcolumns with GIN indexes when you query their contents. - Tune the HikariCP pool to respect Postgres’s
max_connectionslimit.