🏠Spring BootIntroduction to Spring Data JPA

Introduction to Spring Data JPA

The Spring JPA ( also known as spring Data JPA) is one of the spring modules that deal with storing, retrieving, and searching entity objects. In this post, we will take a look at spring JPA in detail using the spring boot application.

Introduction

Spring Data JPA revolves around the org.springframework.data.repository.Repository interface. This interface acts as a marker interface to define the operations that one might do on an entity object.

The CrudRepository, a direct subtype of Repository defines typical operations on entities.

 public interface CrudRepository<T, ID> extends Repository<T, ID> {
    <S extends T> S save(S var1);

    <S extends T> Iterable<S> saveAll(Iterable<S> var1);

    Optional<T> findById(ID var1);

    boolean existsById(ID var1);

    Iterable<T> findAll();

    Iterable<T> findAllById(Iterable<ID> var1);

    long count();

    void deleteById(ID var1);

    void delete(T var1);

    void deleteAllById(Iterable<? extends ID> var1);

    void deleteAll(Iterable<? extends T> var1);

    void deleteAll();
}Code language: Java (java)

The methods you see here relate to an operation you can do with the entities. Spring JPA further extends it to have JpaRepository<T,ID> with the following features.

  1. JPQL Query based operations
  2. Query Methods
  3. Sorting and Pagination support
  4. Support for Streams and Optional

Adding Spring JPA to Spring Boot

To add Spring Data JPA support in spring boot, you should add the spring boot starter data JPA dependency.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>Code language: Java (java)

The spring boot starter data JPA dependency comes with all the auto-configuration necessary to deal with database connections, entity manager, transaction manager, etc.

JPQL Queries

Java persistence query language uses entities and their fields to construct a query instead of using tables and columns. This way, the queries are always type-safe and validated at compile time and run time.

For example, you can write a repository to get all books that have an author’s name and are “active” like the one below.

@Repository
public interface BookRepository extends JpaRepository<Book,Integer> {
    
    @Query("select b from Book b where b.author = ?1 and b.active = ?2")
    List<Book> getActiveBooksByAuthor(String author, boolean active);

}Code language: PHP (php)

Here the @Query annotation helps define a JPQL query with some parameters. We can even do joins here if we can like we do in native queries.

Query methods in Spring Data JPA

Instead of writing queries using @Query annotation, spring offers a mechanism to write the query as a method name. For example, you can write the previous example as below.

List<Book> findBooksByAuthorAndActive(String author,boolean active);
Code language: HTML, XML (xml)

Surprisingly, Spring can parse the method name and create a query based on the method name. In this case, findBooks tells JPA to return all Books and the ByAuthorAndActive refers to which fields to use in the where clause. And the parameters must match the types used in the method name in the same order.

You can further add sorting instructions, distinct results, string matching criteria (LIKE) to these methods. For example, the below method sorts the results in reverse and uses a full-text search.

List<Book> findDistinctBookByAuthorContainingAndActiveOrderByTitleDesc(String search, boolean active);Code language: HTML, XML (xml)

Even some IDEs like IntelliJ provide autocompletion support for these methods.

spring data jpa support in Intellij for a Spring boot application

If you want to see the queries generated by these methods and JPQL, try

Pagination support in Spring JPA

For queries that might result in a large result set, we can request the records from the database in small batches using pagination. In spring Boot we can achieve this using the Pageable interface.

For this, all we need to do is to add a Pageable parameter at the end of the method arguments.

List<Book> findAllByActive(boolean active, Pageable pageable);Code language: HTML, XML (xml)

Once this is in place, we can call this method using PageRequest. For example, the below snippet will result in the first 20 records of all books that are active in the database.

List<Book> books = bookRepository.findAllByActive(true, PageRequest.<em>of</em>(0, 20));Code language: HTML, XML (xml)

Please note that while creating a PageRequest, we are passing a 0 based page index and the number of records to be retrieved. If you need records from 61 to 80, then you will have to create a page request as PageRequest.of(2, 20).

Streams and Optional support

Spring JPA supports streams and Optional they were introduced in Java 8. So instead of returning a collection of objects, you can return a stream.

 Stream<Book> findBooksByAuthorAndActive(String author,boolean active);  Code language: HTML, XML (xml)

And, somewhere in your service layer, you can get the results as stream and process them as you want them.

Similarly, you can avoid NullPointerException by wrapping a single object results in an Optional.

Optional<Book> findBookByIsbnAndActive(String isbn, boolean active);Code language: HTML, XML (xml)

Using this approach, the result will always be non-null. And you can check if your result is available as shown here.

Optional<Book> bookOptional = bookRepository.findBookByIsbnAndActive("123451234512", true);
if (bookOptional.isPresent()) {
    Book book = bookOptional.get();
    //do stuff with book;
}

Related

Similar Posts

Leave a Reply

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