Learn How To Use The PostgreSQL Database with Spring Boot Now! 🧑‍🎓

In this Java code example, we’ll walk through creating a Spring Boot PostgreSQL CRUD app in ten easy steps so get ready to build with Spring Boot and PostgreSQL!

Spring Boot and PostgreSQL power countless database-driven Java applications with their robust framework and advanced relational database features.

Spring Boot and PostgreSQL TOC

Now, let’s take a closer look at this application!

This article was updated on July 2, 2025.

CTO Consulting Services

If you're looking to hire an interim or fractional technology leader then find a time that works for you on my Google Calendar and we can discuss your Temporary CTO, Partial CTO, or Virtual CTO requirements in more detail.

Schedule An Appointment

PostgreSQL Tutorial: Listen For Table Changes

Learn how to listen for changes with the Postgres NOTIFY keyword and monitor database table updates live.

A working example pertaining to Spring Boot and PostgreSQL

In this section we’ll take a look at the Postgres with Spring Boot example in closer detail and go over what’s happening in each step, starting with the preconditions required to run this example.

The Groovy Programming Language (Groovy) allows us to ship a single Groovy example script which contains everything we need in order to run the application in the groovyConsole.

Note that we’re only going to cover necessary blocks of code in steps below.

Preconditions

We will need the following in order to run the example included in this article:

  1. Docker — used to run Postgres locally
  2. Java version 22.0.1 (required) — see OpenJDK on java.net and Oracle Java SE Development Kit 22.0.1 (JDK 22.0.1)
  3. Groovy 4.0.17 (required)
  4. groovyConsole (optional)

Execute the following to run the Postgres interactive terminal (psql) inside the running container:

				
					docker exec -it postgres-container psql -U postgres
				
			

Use this command if you need to debug the script below at any point and need to get a closer look at the database.

Spring Boot and PostgreSQL DB Example Maven Dependencies

The following dependencies are used in this example:

  1. Spring Boot version 3.4.3 (released February 20, 2025)
  2. Spring Boot AutoConfigure
  3. Spring JDBC
  4. Postgres JDBC Driver
  5. Javax Annotation API
  6. SLF4J Simple Provider

The Groovy Grape dependency management system should find these dependencies automatically when the script is executed however for reference purposes I’ve included these here.

Step One: Run Postgres in Docker.

In the first step we need to run Postgres — at stated, this is done via Docker and we can use the command below:

				
					docker run --name postgres-container -e POSTGRES_PASSWORD=password -e POSTGRES_DB=example-db -d -p 5432:5432 postgres
				
			

The following image demonstrates what this should look like:

Docker run command for the PostgreSQL database such that it is available on localhost via port 5432.
Docker command to run the Postgres database locally.

The arguments in this command are explained as follows:

  • Blue — The docker container name is set to postgres-container.
  • Green — The PostgreSQL database password.
  • Orange — The Postgres database name.
  • Yellow — Maps port 5432 on the host machine to port 5432 in the container thereby allowing access to PostgreSQL from localhost.

Step Two: Declare the package name.

In the second step we declare a package name — this is necessary due to the use of the scanBasePackages annotation attribute assigned to the SpringBootApplication annotation (see line #215 in the full example).

Step Three: Grab dependencies and import classes.

We rely on the @Grab annotation in the Groovy Grape dependency management framework to include various dependencies required to run this script.

We also import required classes as well.

Step Four: Acquire an instance of the SLF4J logger.

On line #43 we assign an instance of the SLF4J logger to the log variable.

SLF4J is used in this script so that we can log messages for visual inspection when the script is executed.

Spring Boot and Postgres example Groovy script for steps two through four including pointers to the package, dependency includes using the @Grab annotation, imports, and log variable declaration.
Spring Boot and Postgres example script with steps one through four.

Step Five: Configure the PostgreSQL DataSource and JdbcTemplate Spring beans.

This Spring Framework configuration bean defines two beans:

  • DataSource bean — Configures a PostgreSQL data source (PGDataSource) with the specified host, port, database name, user, and password.
  • JdbcTemplate bean — Creates a JdbcTemplate bean, which simplifies database operations, using the configured DataSource.

These beans enable database connectivity and operations in a Spring application.

Spring Bean configuration class with methods that return a PostgreSQL DataSource and JdbcTemplate bean instances.
Step Five: Spring Bean configuration class with PostgreSQL PGDataSource and Spring JdbcTemplate beans.

Step Six: Implement Spring Boot and Postgres integration through a Spring Repository bean with transactional support.

The sixth step involves creating a repository bean named ExampleRepository which leverages the JdbcTemplate bean to perform various operations on the PostgreSQL database.

The ExampleRepository includes CRUD methods for interacting with the NAMES table as well as utility methods for creating and deleting this table.

Finally, the ExampleRepository has been marked as @Transactional, which ensures that all database operations within this repository are executed as a single unit, thereby providing consistency and rollback capabilities in case of errors.

Transactional Repository bean example used in the Spring Boot and Postgres example with pointers to the JdbcTemplate and each of the CRUD methods.
Transactional Spring Boot Repository bean example which uses an instance of JdbcTemplate to perform CRUD operations on the the PostgreSQL database.

Step Seven: Manage Database Operations with ExampleService in Spring Boot and Postgres.

The ExampleService service bean demonstrates how to manage database interactions in Spring Boot and Postgres applications by delegating operations via the repository layer.

The ExampleService service bean includes methods for executing CRUD operations on the NAMES table.

Additionally, the ExampleService service bean ensures proper lifecycle management by creating the table on startup with the application of the @PostConstruct annotation and cleaning up resources with the application of the @PreDestroy annotation.

The ExampleService service bean includes CRUD methods along with post construct and pre destroy methods that will create and delete the table via the ExampleRepository bean.
Spring Boot Postgres Integration: Step Seven: Service Bean.

Step Eight: Execute application logic with the ExampleCommandLineRunner component.

The ExampleCommandLineRunner code defines a Spring bean that implements the CommandLineRunner interface and which performs several database operations when the application is executed.

The ExampleCommandLineRunner bean uses the ExampleService autowired service bean to execute CRUD operations on the NAMES table and logs each operation’s results for visual inspection purposes.

The ExampleCommandLineRunner Spring Bean implementation with pointers to the use of the @Component annotation, which has been applied to the class, the exampleService bean which is autowired, and several CRUD operations performed on the Postgres database via the exampleService service bean.
ExampleCommandLineRunner Spring Bean showcasing the use of @Component, autowired exampleService, and CRUD operations on a Postgres database.

Step Nine: Run the Spring Boot application and then return.

In this step, the example SpringBootApplication has the required beans configured and the application is then executed.

Once this finishes the SpringApplicationBuilder application context is closed and the script returns.

  • The red pointer points to the package which is used by the scanBasePackages arg in the SpringBootApplication.
  • The orange pointer points to the SpringApplicationBuilder instance which takes the PostgreSQLSpringBootExampleApplication class as a constructor arg.
  • The green pointer points to the beans used in this application — these are assigned to the parent application context.
  • The light blue pointer points to the run method.
  • The dark blue pointer points to the context.close method — once the application execution has completed calling close will terminate the lifecycle of all beans in the Spring application context.
The example SpringBootApplication has the required beans configured and is then run -- once this finishes the SpringApplicationBuilder context is closed.
Configure and run the Spring Boot application.

Step Ten: Run the script and review the output.

In step ten we execute the script and then inspect the output, which should look something like what’s included in the image below.

Run the Spring Boot Postgres example script and examine the output with pointers to the script begin message (in red), the ExampleService start and stop methods (in pink and green), and the script completion message (in blue).
Run the Spring Boot Postgres example script and examine the output.

The pointers in this image are detailed as follows:

  • In red we have the script begins message.
  • In pink and green we have the ExampleService service bean start method and stop method being called respectively — this will create and delete the NAMES table when the Spring application context lifecycle starts and ends.
  • In blue we have the script ends message.

Between the pink and green pointers we have several CRUD operations being performed and we can inspect the output to review what’s taking place.

Spring Boot and PostgreSQL Example on GitHub

Included here is a link to the GitHub gist pertaining to the example used to demonstrate connecting the PostgreSQL Relational Database with Spring Boot.

I’ve also added the full example in the next section, which you should be able to paste into the groovyConsole and run as-is.

				
					/*
 * Precondition:
 *
 * - Java version "22.0.1" 2024-04-16
 * - Groovy version 4.0.17
 */
package com.thospfuller.examples.postgres.database.spring.boot

@GrabConfig(systemClassLoader=true)

@Grab(group='org.springframework.boot', module='spring-boot', version='3.3.0')
@Grab(group='org.springframework.boot', module='spring-boot-autoconfigure', version='3.3.0')
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.context.annotation.Configuration
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Component
import org.springframework.boot.jdbc.DataSourceBuilder

@Grab(group='org.springframework', module='spring-jdbc', version='6.1.8')
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter
import org.springframework.transaction.annotation.Transactional
import org.springframework.context.annotation.Bean
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.WebApplicationType
import org.springframework.stereotype.Service

@Grab(group='com.impossibl.pgjdbc-ng', module='pgjdbc-ng', version='0.8.9')
import com.impossibl.postgres.jdbc.PGDataSource

import javax.sql.DataSource
import java.sql.PreparedStatement

@Grab(group='javax.annotation', module='javax.annotation-api', version='1.3.2')
import javax.annotation.PostConstruct
import javax.annotation.PreDestroy

@Grab(group='org.slf4j', module='slf4j-simple', version='2.0.9')
import org.slf4j.LoggerFactory

def log = LoggerFactory.getLogger(this.class)

log.info "Postgres Database with Spring Boot example begins; args: $args"

@Configuration
class BeanConfiguration {

  @Bean
  DataSource getDataSource () {

    PGDataSource dataSource = new PGDataSource()

    dataSource.setHost("0.0.0.0")
    dataSource.setPort(5432)
    dataSource.setDatabaseName("postgres")
    dataSource.setUser("postgres")
    dataSource.setPassword("password")

    return dataSource
  }

  @Bean  
  JdbcTemplate getJdbcTemplate (DataSource dataSource) {
    return new JdbcTemplate (dataSource)
  }
}

@Repository
@Transactional
class ExampleRepository {

  private static final def log = LoggerFactory.getLogger(ExampleRepository)

  static final def TABLE_NAME = "NAMES"

  @Autowired
  private JdbcTemplate jdbcTemplate

  void createExampleTable () {

    log.info "createExampleTable: method begins."

    jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name VARCHAR(255));")

    log.info "createExampleTable: method ends."
  }

  def deleteExampleTable () {

    log.info "deleteExampleTable: method begins."

    jdbcTemplate.execute("DROP TABLE IF EXISTS ${TABLE_NAME};")

    log.info "deleteExampleTable: method ends."
  }

  def addNames (String... names) {
    return addNames (names as List<String>)
  }

  def addNames (List<String> nameList) {

    return jdbcTemplate.batchUpdate(
      "INSERT INTO ${TABLE_NAME} (name) VALUES (?);",
      nameList,
      nameList.size (),
      { PreparedStatement preparedStatement, String name ->
        preparedStatement.setString(1, name)
      } as ParameterizedPreparedStatementSetter<String>
    )
  }

  def updateName (int id, String newName) {

    return jdbcTemplate.update(
      "UPDATE ${TABLE_NAME} SET NAME = ? WHERE ID = ?;",
      newName,
      id
    )
  }

  def deleteName (int id) {

    return jdbcTemplate.update(
      "DELETE FROM ${TABLE_NAME} WHERE ID = ?;",
      id
    )
  }

  def readNames () {
    return jdbcTemplate.queryForList ("select name from ${TABLE_NAME}")
  }
}

@Service
class ExampleService {

  private static final def log = LoggerFactory.getLogger(ExampleService)

  @Autowired
  def exampleRepository

  @PostConstruct
  def start () {

    log.info "start: method begins."

    exampleRepository.createExampleTable ()

    log.info "start: method ends."
  }

  @PreDestroy
  def stop () {

    log.info "stop: method begins."

    exampleRepository.deleteExampleTable ()

    log.info "stop: method ends."
  }

  def addNames (String... nameList) {
    return exampleRepository.addNames (nameList)
  }

  def updateName (int id, String newName) {
    return exampleRepository.updateName (id, newName)
  }

  def deleteName (int id) {
    return exampleRepository.deleteName (id)
  }

  def readNames () {
    return exampleRepository.readNames ()
  }
}

@Component
class ExampleCommandLineRunner implements CommandLineRunner {

  private static final def log = LoggerFactory.getLogger(PostgreSQLSpringBootExampleApplication)

  @Autowired
  private def exampleService

  @Override
  public void run (String... args) {

    log.info "run: method begins; args: $args"

    def namesAdded = exampleService.addNames ("aaa", "bbb", "ccc", "ddd")

    log.info "namesAdded: $namesAdded"

    def updateResult = exampleService.updateName (2, "ZZZ")

    def names = exampleService.readNames ()

    log.info "updateResult: $updateResult, names after update: $names"

    def deletedNames = exampleService.deleteName (2)

    names = exampleService.readNames ()

    log.info "deletedNames: $deletedNames, names after deletion: $names"

    log.info "run: method ends."
  }
}

@SpringBootApplication(scanBasePackages = ["com.thospfuller.examples.postgres.database.spring.boot"])
class PostgreSQLSpringBootExampleApplication {}

def springApplicationBuilder = new SpringApplicationBuilder(PostgreSQLSpringBootExampleApplication)

def context = springApplicationBuilder
  .profiles("default")
  .web(WebApplicationType.NONE)
  .parent (
    BeanConfiguration,
    ExampleRepository,
    ExampleService,
    ExampleCommandLineRunner
  )
  .run(args)

context.close ()

log.info "...done!"

return
				
			

This concludes this section — the article conclusion follows.

Spring Boot and PostgreSQL Tutorial Conclusion

This Spring Boot and PostgreSQL guide walked you through ten easy steps to integrate these tools, including a Groovy example, for a seamless Java project setup.

Integrating Spring Boot with the Postgres database streamlines application development by leveraging Spring Boot’s robust framework and PostgreSQL’s advanced capabilities.

Combining these two technologies facilitates efficient data management and a scalable architecture, making it an ideal choice for software engineers building database-driven applications.

Are you ready to build applications powered by PostgreSQL with Spring Boot?

Try these how-to steps and share your feedback in the comments!

Frequently Asked Questions (FAQ)

Does Spring Boot work with PostgreSQL?
Yes Spring Boot and Postgres can be seamlessly connected and we cover how to do this in ten simple steps along with working example code which is written in the Groovy Programming Language.

See Also

  1. Learn how to implement a simple Jedis pub sub client in three simple steps!
  2. Try the COBOL Copybook Reader here!
author avatar
ThosPFuller
I am a software engineer based in Northern Virginia (USA) and this website focuses on content engineering, web development, Technical SEO, Search Engine Optimization (SEO).

Leave a Reply