Spring Data JPA - Repositories
There are 3 repository interfaces that you should know when you use Spring Data JPA:
- CrudRepository: https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html
- The CrudRepository interface defines a repository that offers standard create, read, update and delete operations.
- PagingAndSortingRepository: https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/PagingAndSortingRepository.html
- The PagingAndSortingRepository extends the CrudRepository and adds findAll methods that enable you to sort the result and to retrieve it in a paginated way.
- JpaRepository: https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html
- The JpaRepository adds JPA-specific methods, like flush() to trigger a flush on the persistence context or findAll(Example<S> example) to find entities by example, to the PagingAndSortingRepository.
Both CrudRepository and PagingAndSortingRepository interfaces are also supported by other Spring Data projects, so that you can apply the same concepts to different datastores.
The model

Defining an entity-specific repository
You can use any of the standard interfaces to define your own repository definition. You, therefore, need to extend one of Spring Data JPA’s interface, e.g. the CrudRepository interfaces and type it to the entity class and its primary key class.
Let’s take a look at a simple example. The Book entity is a normal JPA entity with a generated primary key of type Long, a title and a many-to-many association to the Author entity.
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Version
private int version;
private String title;
@ManyToMany
@JoinTable(name = "book_author",
joinColumns = { @JoinColumn(name = "fk_book") },
inverseJoinColumns = { @JoinColumn(name = "fk_author") })
private List authors = new ArrayList();
...
}
If you want to define a CRUD repository for this entity, you need to extend Spring Data JPA’s CrudRepository interface and type it to Book and Long. In the following code snippet, I also added the findByTitle method to the repository to find a Book entity by a given title.
public interface BookRepository extends CrudRepository<Book, Long> {
Book findByTitle(String title);
}
Working with Repositories After you defined your repository interface, you can use the @Autowired annotation to inject it into your service implementation. Spring Data will then provide you with a proxy implementation of your repository interface. This proxy provides default implementations for all methods defined in the interface. If you need to adapt the default functionality, you can provide your own repository implementations. But that a topic for another article. Let’s focus on Spring Data JPA’s standard functionality for now.
In your business code, you can then use the injected repository to read entities from the database and to persist new or changed entities. The test class in the following code snippet uses the BookRepository to find a Book entity with the title ‘Hibernate Tips’ and to persist a new Book entity.
@RunWith(SpringRunner.class)
@SpringBootTest
public class GettingStartedApplicationTests {
Logger log = Logger.getLogger(this.getClass().getName());
@Autowired
private BookRepository bookRepository;
@Test
@Transactional
public void testByTitle() {
log.info("... testByTitle ...");
Book b = bookRepository.findByTitle("Hibernate Tips");
Assert.assertEquals(new Long(1), b.getId());
}
@Test
@Transactional
public void testPersistBook() {
log.info("... testPersistBook ...");
Book b = new Book();
b.setTitle("Hibernate Tips - More than 70 solutions to common Hibernate problems");
bookRepository.save(b);
}
}
References
https://thorben-janssen.com/what-is-spring-data-jpa-and-why-should-you-use-it/#repositories