In the previous chapter, you learned about Spring Boot’s fundamentals to develop our backend application, such as dependency injection, beans, and annotations. In addition, we now know how to create a Spring Boot project using Spring Initializr.
This chapter will teach you how to connect your Spring Boot application to a database by adding a PSQL container and PostgreSQL dependencies and accessing data using the Java Persistence API (JPA).
In this chapter, we will cover the following topics:
Here is what you need to complete this chapter:
This section will teach us how to set up and configure our PostgreSQL in our terminal by using the conventional method, using the installer, or through a Docker container. But first, let’s discuss what PostgreSQL is and what its advantages are.
PostgreSQL is an open source object-relational database system that uses the SQL language to store and handle complicated and large workloads. PostgreSQL also supports both SQL (relational) and JSON (non-relational) querying. It is commonly used as primary data storage for geospatial and analytics applications because of its flexibility and rich features. Its community has improved and continuously backed it for more than 20 years to add more features and reliability to the database system.
PostgreSQL’s flexibility means that it is widely used in developing applications. Here are some of the everyday use cases:
Here’s a list of some of the features that PostgreSQL offers:
Now that we have an overview of the features and use cases of PostgreSQL, let’s move on to installing it on our terminal.
There are two ways for us to set up our PostgreSQL in our development terminal. The two approaches are as follows:
PostgreSQL was mainly developed for Unix-like platforms. However, it was created to be portable and can be installed on Windows and macOS platforms.
The first step we need to take is to download the PostgreSQL installer through this URL: https://www.enterprisedb.com/downloads/postgres-postgresql-downloads.
Figure 4.1 – PostgreSQL installation
The steps for the three operating systems are the same, and we only need to configure some settings:
Figure 4.2 – The PostgreSQL installer (specify the path to install)
In the preceding example, we have chosen the default installation path. Click Next again, which will ask us what components we want to install. The components that we select are as follows:
Figure 4.3 – The PostgreSQL installer (select the needed components)
We have checked all the components in the preceding example, as we will need all of them throughout our development.
Figure 4.4 – The PostgreSQL installer (select the directory for the data)
In the preceding example, we can see that the default path is the same as where PostgreSQL is installed, and it has created a new folder named data. It is recommended that you use the default path.
Figure 4.5 – The PostgreSQL installer (select a locale for the database cluster)
In the preceding example, we have selected [Default locale] as our locale for the database.
After installation, we can verify whether PostgreSQL is installed successfully by checking the currently installed version.
Figure 4.6 – The PostgreSQL installer (displaying the version of PostgreSQL)
In the preceding example, we can see that we have successfully installed PostgreSQL version 13.4 on our terminal.
Now, let’s learn how to install and configure PostgreSQL using Docker.
We have installed PostgreSQL on our terminal using the conventional installer; now, we will learn to configure PostgreSQL using Docker. This method will help us skip the complex steps in configuring PostgreSQL for us to start with development and provide a GUI for database management:
Docker run --name postgresql-container -p 5434:5434 -e POSTGRES_PASSWORD=pass -d postgres
The preceding command will pull the PSQL from Docker-hub. The postgresql-container part in the command can be replaced, as this is a container name that we can define. The POSTGRES_PASSWORD parameter is the password for the postgres admin, which we can also configure.
Figure 4.7 – The PostgreSQL installation using Docker
In the preceding example, we have executed the Docker ps -a command, and we can see that our PostgreSQL image has been pulled:
Figure 4.8 – The PostgreSQL installation using Docker (viewing the container in Docker Desktop)
We have successfully configured our PostgreSQL with Docker. We can connect this to our pgAdmin by creating a new server with our terminal IP address and port.
We have configured the PostgreSQL database in our terminal. Now, we will learn about Spring Data JPA and its importance in developing Spring applications.
Spring Data JPA (Java Persistence API) is a widely used specification for managing relational data in Java applications. It helps develop Spring, as it reduces boilerplate code by not implementing read and write operations. It also handles the complex process involved in JDBC-based accessing of database and object-relational mappings.
Before discussing Spring Data JPA, let’s discuss its clear advantages and why it is commonly used in Spring development.
The following are the advantages of Spring Data JPA:
For example, we have a BlogRepository class in our application; when we extend it with the CrudRepository<Blog, Long> interface, it will have methods that have the following functionalities:
Extending the repository with the interface provided by Spring Data JPA includes all data-related methods, which allows us to focus more on business logic.
public interface BlogRepository extends CrudRepository<Blog, Long> {
Blog findByAuthor(String author);
}
In the preceding example, we have created a findByAuthor() method, which will allow Spring to generate a query and set the parameters as bind parameter values. It will execute the query once we call the method.
Spring Data JPA provides repositories that provide different methods for data-related implementations. The repositories are the following:
We have learned about the different repositories we can use with Spring Data JPA. We will now take a look at Spring Data JPA on Spring Boot.
For us to implement Spring Data JPA in our application, we need the following components:
For example, we will create an entity for Villain by making a plain class and adding @Entity annotations to indicate the Villain class as a JPA entity. The entity will be used as the type for extending our repository:
@Entity public class Villain { @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "UUID") @Column(nullable = false, updatable = false) private UUID id; @NotNull(message = "First Name is required") private String firstName; private String lastName; private String house; private String knownAs; }
We can see in the preceding example that our Villain class is annotated with @Entity, indicating it as a JPA entity. We have also defined an id field of the UUID type and annotated it with @Id to indicate that this is the primary key, and @GeneratedValue, where we specified that this is automatically generated using strategy = GenerationType.The AUTO and the ID generated should be of the UUID type, using generator = "UUID".
In the previous example, we have a Villain entity. To implement the CRUD operations, we will create a VillainRepository interface and extend it with CrudRepository, with a type of Villain and UUID:
@Repository public interface VillainRepository extends CrudRepository<Villain, UUID> { // custom composite repository here }
@Service
public class VillainService {
private final VillainRepository villainRepository;
@Autowired
public VillainService (VillainRepository villainRepository) {
this. villainRepository = villainRepository;
}
public Iterable<Villain> findAllVillains() {
return villainRepository.findAll();
}
public Villain findVillainById(UUID id) {
return findOrThrow(id);
}
In the preceding example, we can see that we have injected VillainRepository in VillainService using the @Autowired annotation.
Let’s continue with the following methods using the same file:
public void removeVillainById(UUID id) { villainRepository.deleteById(id); } public Villain addVillain(Villain villain) { return villainRepository.save(villain); } public void updateVillain(UUID id, Villain villain) { findOrThrow(id); villainRepository.save(villain); } private Villain findOrThrow(final UUID id) { return villainRepository .findById(id) .orElseThrow( () -> new NotFoundException("Villain by id " + id + " was not found") ); } }
We have also created methods by using the built-in JPA implementation, such as save(), deleteById(), findAll(), and findById(), which are found in the CrudRepository interface. The service can now be injected into our controllers or other services to use the methods.
We’ve now learned about Spring Data JPA, its advantages, and an overview of implementation on Spring JPA. In the next section, we will learn how to add Spring Data JPA and PostgreSQL dependencies to our Spring Boot application.
This section will add Spring Data JPA, PostgreSQL, and other valuable dependencies to our application. We will add the dependencies with Spring Initializr and an existing Spring Boot project.
Adding dependencies after creating a Spring Boot application using Spring Initializr is simple. We only need to select the dependencies on Initializr before generating our project:
Figure 4.9 – Adding dependencies in Spring Initializr
After successfully adding the dependencies, we can see that our dependencies are already listed.
Figure 4.10 – The Spring Boot application (a view of pom.xml)
In the preceding example, we can see that the Spring Boot application is generated with Maven, and we can see that our pom.xml file has included the dependencies we added in Spring Initializr:
Figure 4.11 – The Spring Boot application (a view of build.gradle)
Now, in the preceding example, where the Spring Boot application is generated with Gradle, we can see the list of dependencies is already added under the build.gradle file.
We will now add the dependencies to an existing Spring Boot application.
In the previous example, we added the dependencies to generate our Spring Boot application using Spring Initializr. Now, we will add our dependencies to an existing application. It is simple to add a dependency to an existing Spring app; we only need to modify the pom.xml (Maven) or build.gradle (Gradle) files.
To install Spring Data JPA, the H2 database, and PostgreSQL Driver using Maven, we will add the dependencies in the form of XML, as follows:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
And for a Spring application using Gradle, we will add the dependencies as follows:
dependencies { implementation 'org.springframework.boot:spring-boot- starter-data-jpa' runtimeOnly 'com.h2database:h2' runtimeOnly 'org.postgresql:postgresql' }
IntelliJ will automatically recognize the added dependencies and install them for the project, and we can successfully build and run the Spring Boot application on the fly.
We have learned how to add Spring Data JPA and PostgreSQL Driver to our Spring Boot application. In the next section, we will learn how to connect our Spring Boot application to our PostgreSQL database.
We have already configured our PostgreSQL database and initialized our Spring Boot application with the needed dependencies. Now, we will learn how to connect our PostgreSQL to our application. There are two ways we can connect to our database – the first is through Spring JDBC, and the other is Spring Data JPA. Spring Data JPA is the most convenient way to connect to our database, but we will demonstrate both methods in this section.
The first thing we need to do is configure the database properties in our Spring Boot application. We need to specify the server URL of the database, the admin username, and the password by adding the following source code to the application.properties file:
spring.datasource.url=jdbc:postgresql://localhost:5432/springDB spring.datasource.username=postgres spring.datasource.password=password
In the preceding example, we can see that we have configured the basic connection settings for our PostgreSQL. springDB on the URL will be the name of the database in PostgreSQL, which should already exist on our server.
The first method to connect to the database is by using Spring JDBC. We will add an additional dependency to our application for us to use this method.
To add JDBC, we will add the following code to our pom.xml (Maven) or build.gradle (Gradle) files:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
After successfully adding the JDBC dependency, we can now use JdbcTemplate to execute queries on our application:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.jdbc.core.JdbcTemplate; @SpringBootApplication public class AwesomeJavaProject { @Autowired private JdbcTemplate jdbcTemplate; public static void main(String[] args) { SpringApplication.run(AwesomeJavaProject .class, args); } @Override public void run(String... args) throws Exception { String sql = "INSERT INTO blog (title, author, body) VALUES ("+ "'Awesome Java Project', 'Seiji Villafranca', 'This is an awesome blog for java')"; int rows = jdbcTemplate.update(sql); } }
In the preceding example, we can execute database statements such as INSERT in our application and call the update() method to modify data in the database.
The second method is by using the Spring Data JPA plugin. The first step we need to take is to add additional details to the application.properties file:
spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.format_sql=true
After adding the new settings, we can now create Entity and Repository for a specific table in our application – for example, we have a Blog table:
package net.codejava; import javax.persistence.*; @Entity @Table(name = "blog") public class Blog { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String title; private String body; private String author; }
In the preceding example, we have created a Blog class and annotated it with @Entity and @Table to indicate that this is an object connected to our database table:
package net.codejava; import org.springframework.data.JPA.repository.JpaRepository; public interface BlogRepository extends JpaRepository<Blog, Integer> { }
After creating our entity, we have made the repository for the blog, which can be extended by the repositories provided by JPA. BlogRepository can now be injected into our services or controllers to read, add, modify, or delete data on our database.
That brings you to the end of this chapter. Let’s have a recap of the valuable things you have learned. You learned how to set up PostgreSQL on your local machine using the installer or Docker container.
You have also learned about the concepts and advantages of Spring Data JPA in Spring Boot and how to add it to your application, which is helpful in creating services with CRUD capabilities with less boilerplate code.
Last but not least, you learned how to connect your Spring Boot application with the PostgreSQL database using JDBC and Spring Data JPA.
In the next chapter, we will be learning how to start our server, how to add controllers, models, and services in our code, and about Redis for caching.