1. Overview

In this tutorial, we’re going to cover the use of the @EmbeddedId annotation and “findBy” method for querying a composite key based JPA entity.

Hence we’ll be using @EmbeddeId and @Embeddable annotations to represent composite keys in JPA entities. We also need to use Spring JpaRepository to achieve our goal.

We’ll concentrate on querying objects by partial primary key.

2. Need for @Embeddable* and *@EmbeddedId

In software, we come across many use cases when we need to have a composite primary key to define an entry in a table. Composite primary keys are keys that use more than one column to identify a row in the table uniquely.

We represent a composite primary key in Spring Data by using the @Embeddable annotation on a class. This key is then embedded in the table’s corresponding entity class as the composite primary key by using the @EmbeddedId annotation on a field of the @Embeddable type.

3. Example

Consider a book table, where a book record has a composite primary key consisting of author and name. Sometimes, we might want to find books by a part of the primary key. For example, a user might want to search for books only by a particular author. We’ll learn how to do this with JPA.

Our primary application will consist of an @Embeddable BookId and @Entity Book with @EmbeddedId BookId.

3.1. @Embeddable

Let’s define our BookId class in this section. The author and name will specify a unique BookId — the class is Serializable and implements both equals and hashCode methods:

@Embeddable
public class BookId implements Serializable {

    private String author;
    private String name;

    // standard getters and setters
}

3.2. @Entity and @EmbeddedId

Our Book entity has @EmbeddedId BookId and other fields related to a book. BookId tells JPA that the Book entity has a composite key:

@Entity
public class Book {

    @EmbeddedId
    private BookId id;
    private String genre;
    private Integer price;

    //standard getters and setters
}

3.3. JPA Repository and Method Naming

Let us quickly define our JPA repository interface by extending the JpaRepository with entity Book as well as BookId:

@Repository
public interface BookRepository extends JpaRepository<Book, BookId> {

    List<Book> findByIdName(String name);

    List<Book> findByIdAuthor(String author);
}

We use a part of the id variable’s field names to derive our Spring Data query methods. Hence, JPA interprets the partial primary key query as:

findByIdName -> directive "findBy" field "id.name"
findByIdAuthor -> directive "findBy" field "id.author"

4. Conclusion

JPA can be used to efficiently map composite keys and query them via derived queries.

In this article, we saw a small example of running a partial id field search. We looked at the @Embeddable annotation to represent the composite primary key and the @EmbeddedId annotation to insert a composite key in an entity.

Finally, we saw how to use the JpaRepository findBy derived methods to search with partial id fields.

As always, the example code for this tutorial is available over on GitHub.