Using JPA to Create Instances and Save to API / Database

Lucas Thinnes
4 min readNov 10, 2021

--

In my previous post I explained how to connect a Java backend to a Postgres database, but just because the two are connected doesn’t mean that we have everything we need within the realm of maintaining an API / Database. In fact, where the previous post left off, we didn’t even have any tables set up within the database, just the connectivity confirmed. In this one I want to go over the process of creating instances of a given object in order to add or remove data from the API. I hope this helps solidify the concept within your application, or if you have been following along, teaches you something new about this whole process!

ACTIVATING JPA SEQUENCES

To pick up where we left off, we will have to navigate over to our “Bird.java” file where the outline for our class along with the getters and setters are stored. We will need to add a few extra annotations, specifically “@Entity”, “@Table”, “@Id”, “@SequenceGenerator” and “@GeneratedValue”. These are used to activate the table within the database and populate it with the fields specified within our Bird class. The code will look like this, starting before the initializer of the Bird class:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity
@Table
public class Bird {
@Id
@SequenceGenerator(
name = "bird_sequence",
sequenceName = "bird_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "bird_sequence"
)

A quick side note for VIM users: if you do not want to be writing out the import statements moving forward I highly recommend running a :CocInstall coc-java if you are using coc.nvim and also adding Easy Java to your init.vim.

When we compile and restart our server, it will include this in the shell:

The bird table has now been created!

ASSEMBLING THE REPOSITORY CLASS

The purpose of making a JPA repository is to efficiently store, update and extract the data from our backend. It isn’t a class per say, and so will be instantiated a little bit differently. Here is the code for the “BirdRepository.java” that I have created:

package com.example.demo.bird;import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BirdRepository extends JpaRepository<Bird, Long> {
}

As you can see, it is a public interface instead of a public class.

Next, we have to make some changes to the BirdService.java file to include the repository we created. This involves autowiring a BirdService method to be set to the current repository, then modifying the “getBirds” method to return a .findAll() call on the repository. The modified class will look like this:

@Service
public class BirdService {
private final BirdRepository birdRepository;@Autowired
public BirdService(BirdRepository birdRepository) {
this.birdRepository = birdRepository;
}
public List<Bird> getBirds() {
return birdRepository.findAll();
}
}

That’s all there is to it! We can now save exotic birds into our database! I will walk through how to do that next.

SAVING INSTANCES

Real quick, since we modified our code and restarted the server with the database connection, we’ll see that our endpoint now returns an empty array:

To get our instances to show up, we have to make a new class called BirdConfig.java and include it with this return statement which makes use of the Configuration, CommandLineRunner and Bean annotations. I included a few extra instances to be saved so it can be demonstrated this is unique to the previous version of the API we got up and running:

package com.example.demo.bird;import java.util.List;import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BirdConfig {
@Bean
CommandLineRunner commandLineRunner(BirdRepository repository) {
return args -> {
Bird flamingo = new Bird(
"Flamingo",
"Phoenicopterus",
1831
);
Bird goldfinch = new Bird(
"Goldfinch",
"Granivore",
1758
);
Bird albatross = new Bird(
"Albatross",
"Diomedeldae",
1840
);
repository.saveAll(
List.of(flamingo, goldfinch, albatross)
);
};
}
}

The process here is this:

  • A class is labeled with the “Configuration” annotation.
  • It calls the bean & CommandLineRunner which takes in the repository as arguments.
  • It then returns the arguments of the data we want to store.
  • Each instance is set to its own variable and then saved via List.of using repository.saveAll().

Now, if we recompile and refresh our server, check this out:

Woohoo! An array of objects!

To prove it is in the database, we can head to Postgres and check the following:

Congratulations on making it this far, and I hope you have enjoyed the process!

--

--