JavaSpringTechnology

Spring Data JPA Composite Key with @EmbeddedId

This post we will learn about dealing with Composite Keys with @EmbeddedId in Spring Data & JPA. We will see how we can define a table with composite key, specify the keys and see an example of putting an entry into the table and finding with the help of Composite key. 

If you want to learn how to use Spring Data JPA with a Spring Boot application please read our Spring Data and JPA Tutorial

1 Primary Key and Composite Primary Key

Although Database tables and their primary or index keys is too vast and sort of off scope of this post, we will quickly have a look what is Primary Key and Composite Primary Key. For your own interest and knowledge consider specific material to understand the concepts thoroughly. 

1.1 Primary Key

As a practice each row in a database table should be uniquely identified by a key column. This column can be a data column which has unique values or a specifically created column of sequential numbers or random ids like UUID. We call such a key column as a Primary Key of the table.

Having such a sequential Id or UUID sometimes, doesn’t help search operations. Consider an Employee table where a sequentially generated employee_id is a Primary key. Most of the cases, no one would search an employee with employee_id. More possible search keys would be name, designation, department or a combination. To help faster searches we may need to create additional indexes on search columns. 

1.2 Composite Primary Key

As an alternative, we can create a Primary Key of multiple columns which is called as Composite Primary Key. The Spring Data & JPA does support composite primary keys and today we will see how.

For this tutorial we will consider a table that stores Songs details such as name, genre, artist, rating, download link etc. We will create a Composite Primary Key of name, genre, and artist. For now we will assume that the song name, genre, and artist can uniquely identify a Song. 

2 Config files

Here is our build.gradle which has some Spring Boot specific dependencies, along with Spring Data and MySql. Additionally we have also added a dependency for H2 DatabaseH2 is a in-memory sql database, which is ideal for quick testing. So we will use MySql for service execution and H2 for unit tests.

Now, have a look at application.yml. It has standard Spring Boot specific datasource configuration along with hibernate configs.

The ddl-auto: update tells hibernate to create the tables on application startup, if they do not present already. 

3 Entity Bean and Repository

Let’s write our Entity Bean and Repository interface now. 

3.1 Id class (SongId)

At first, let’s create our ID class. As discussed before, our Song table has a composite key of name, genre, and artist. Instead of having these fields in Song entity, we will more them to a separate SongId class and refer the SongId class in Song.

The annotation @Embeddable is to tell that this is a Composite Id class and can be embedded into an entity bean.

3.2 Song Entity Bean

Now, lets write the @Entity bean and add the SongId as a field marked with @Embedded.

3.3 Song Repository Interface

Now, we have our Entity bean and Embedded Id in place. This time we will write the SongsRepository which extends from Spring Data‘s CrudRepository.

4 Tests

Here is simple test for our Repository. We use H2 a in-memory database for our test. The @DataJpaTest of Spring Boot does the auto-configuration of H2 Database and provides @TestEntityManager which we have autowired.

4.1 repoCorrectlySavesGivenSong

In this test we prepare a test Song along with a SongId and use our Repository to save it to the H2 database. We then, use TestEntityManager to retrieve the Song from database passing in the SongId, and then verify all the things we stored as retrieved as they were. 

4.2 repoCorrectlyFindsSongById

In this case we have created total 4 Songs along with different SongId. We used TestEntityManager to persist each of them to the database. We then, used our Responsitory under test and asked it to find a Song by id by passing in one of those 4 ids we created. Once retrieved we verified the exact same song was returned. 

5 Conclusion

In this Spring Data JPA Composite Key with @EmbeddedId tutorial we first saw what is Primary Key and why it is important. We also saw why some tables can’t have a unique column and something, why having a auto-generated id won’t help in searches. 
We then learned in brief about the concept of Composite Primary Key and we saw how Spring Data and JPA support it with the help of @EmbeddedId annotation.

We have also seen how to use Spring Boot‘s TestEntityManager to verify our repository and the entity beans work correctly.

We have drafted a separate article for how to perform search by using some of many columns in a primary key. If you are interested knowing about it, please visit Spring Data JPA find by @EmbeddedId Partially.


For full source code of the examples used here, please visit https://github.com/amitrp/spring-date-jpa-embeddedid.


Leave a Reply

Your email address will not be published. Required fields are marked *