Skip to content
Spring Boot sb databases 3 min read

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: jsonb supports 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 typePostgres columnNotes
UUIDuuidNative UUID storage, ideal for IDs
Map/POJO + @JdbcTypeCode(JSON)jsonbIndexable JSON documents
String[] / Listtext[]Native array columns
InstanttimestamptzTimezone-aware timestamps

Best Practices

  • Keep credentials out of source control; inject them via environment variables or a secrets manager.
  • Use ddl-auto: validate with Flyway or Liquibase migrations in production.
  • Prefer timestamptz for timestamps so values are stored unambiguously in UTC.
  • Index jsonb columns with GIN indexes when you query their contents.
  • Tune the HikariCP pool to respect Postgres’s max_connections limit.
Last updated June 13, 2026
Was this helpful?