Connecting a Java Backend to a Postgres Database
This week I learned how to connect a Java API to a Postgres database and I wanted to share this technique with the world! This sort of rides atop the coattails of the previous article I wrote, so if that is your reference point for creating Java APIs, this should feel like a very natural development.
INITIALIZE A SPRINGBOOT PROJECT
The first step is to head over to the Springboot Initializer. You can create a project with the default settings but under “dependencies”, be sure to add Spring Web, Spring Data JPA and the PostgreSQL driver as such:
I changed the name of my directory to “db-connect” for the sake of this tutorial. The very first thing you will want to do before starting your server in this project will be to comment out the JPA dependency code within the pom.xml file found in the root project directory, this will block the server from starting as no database has been created or connected to yet:
Perfect, let’s move on!
IMPLEMENTING API
As you will see by navigating to src/main/java/com/example/demo/DemoApplication.java, the default code we are given looks like this:
package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
To review what I covered last week, the two annotations we will need to import are the Rest Controller, which enables the ability to create a restful API, and Get Mapping, which allows us to make get requests to our server. Add an “@GetMapping” beneath the “@SpringBootApplication” (quoted to avoid “atting” people on this site) and a “@GetMapping” beneath the main method, followed by this method to check our API:
public string working() {
return "It's working!";
}
When we restart our server (which if using the command line / Vim is done running “mvn compile” followed by “mvn exec:java -Dexec.mainClass=com.example.demo.DemoApplication”) and navigate to localhost:8080 we will now see this:
Just like that, we can return from the backend to our server!
CREATING OUR CLASS
First step to creating our class it to make a directory within our “demo” folder. For this tutorial I want to make an “exotic birds” class, so feel free to replicate or create something you would like to see. I made a folder titled “bird” with a Birds.java file inside. Beneath the import statement we will want to initialize our class with name, family (genus) and the year they were formally introduced to the animal kingdom in the realm of our awareness. We will want to follow that up with getters and setters for each parameter then convert them to strings. Here is the code I have written for this example:
package com.example.demo.bird;public class Bird {
private Long id;
private String name;
private String family;
private Integer yearIntroduced;public Bird() {
}public Bird(Long id,
String name,
String family,
Integer yearIntroduced) {
this.id = id;
this.name = name;
this.family = family;
this.yearIntroduced = yearIntroduced;
}public Bird(String name,
String family,
Integer yearIntroduced) {
this.name = name;
this.family = family;
this.yearIntroduced = yearIntroduced;
}public Long getId() {
return id;
}public void setId(Long id) {
this.id = id;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}
public String getFamily() {
return family;
}public void setFamily(String family) {
this.family = family;
}public Integer getYearIntroduced() {
return yearIntroduced;
}public void setYearIntroduced(Integer yearIntroduced) {
this.yearIntroduced = yearIntroduced;
}@Override
public String toString() {
return "Bird{" +
"id=" + id +
"name=" + name +
"family=" + family +
"yearIntroduced=" + yearIntroduced +
'}';
}}
Now, we head over to the DemoApplication.java file and make these changes beneath the GetMapping use to render an instance of an exotic bird:
public List<Bird> getBird() {
return List.of(
new Bird(
1L,
"Flamingo",
"Phoenicopterus",
1831
)
);
}
Which will produce this when we recompile and reload our server:
It almost looks like an actual API, doesn’t it?!
CREATING A BIRD CONTROLLER & SERVICE LAYER
Next, we will want to create a file within our bird directory called BirdController.java. This controller will require RestController, RequestMapping, GetMapping and Autowired annotations, and with a path passed to the RequestMapping of “api/v1/birds” so that will be the new endpoint tacked on to our server. The service layer will contain the instance we created in the DemoApplication for more efficient management, and will make use of the “@Service” annotation. My code for this portion looks like this in DemoApplication:
package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
This in BirdService.java:
package com.example.demo.bird;import java.util.List;public class BirdService {
public List<Bird> getBirds() {
return List.of(
new Bird(
1L,
"Flamingo",
"Phoenicopterus",
1831
)
);
}
}
And this in the BirdController.java:
package com.example.demo.bird;import java.util.List;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping(path = "api/v1/bird")
public class BirdController {private final BirdService birdService;@Autowiredpublic BirdController(BirdService birdService) {
this.birdService = birdService;
}@GetMapping
public List<Bird> getBirds() {
return birdService.getBirds();
}
}
We now access our API from the path localhost:8080/api/v1/bird!
CREATING AND CONNECTING TO A DATABASE WITH JPA
To initialize this procedure we will want to head over to the application.properties file within the src/main/resources directory. To configure this for Postgres access, we will want to add this code to the file:
spring.datasource.url=jdbc:postgresql://localhost:5432/bird
spring.datasource.username=
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.format_sql=true
After this is complete, head over to the terminal and type “psql” to start PostgreSQL and create a new database by typing in “CREATE DATABSE bird;”. You should receive a “CREATE DATABASE” notification once this is complete. Verify you have access to this database by entering “GRANT ALL PRIVILEGES ON DATABASE “bird” TO [yourusername];” and “GRANT ALL PRIVILEGES ON DATABASE “bird” TO postgres;”. These should produce a “GRANT” notification. Connect to the database via the command “\c bird”. This should notify you that you are now connected to the database under the privileges of your username. Head back to the pom.xml and uncomment the JPA dependency and restart the server: you will now be connected to the Postgres database via Hikari!
Just like that we have connected to a database. In the next post I will explain how to seed instances of our birds within the database. Until next time!