IntelliJ reports that there is more than one bean of a repository, although app starts up fine

I’ve come across an issue recently in a project where I was using Spring Data JPA. I had a repository defined like this:

@Repository
public interface QuestionCategoryRepository extends JpaRepository<QuestionCategory, Long> {

}

I also had a service class where I injected this repository:

@Inject
private QuestionCategoryRepository questionCategoryRepository;

I noticed, that IntelliJ reported the following error: “There is more than one bean of QuestionCategoryRepository type”. It seemed wierd to me, so I went ahead and started my application. The context was built successfully and there were no problems with the startup at all.

It turned out that IntelliJ really had provided me a useful hint, because I noticed that I have an

@ComponentScan(basePackages = "...")

annotation on my class that is used for persistence related configuration. The scope of this annotation was involving the package where I had my repositories defined.

This is why IntelliJ believed, that there are two definitions.

Actually, there were three.

I also noticed that I have

@EnableJpaRepositories(basePackages = "...")

on my configuration class, pointing to the packes where my repositories reside.

It turned out that I can remove both the @Repository annotation and the @ComponentScan as well, becauses the @EnableJpaRepositories was enough to detect my repositories. Of course, @ComponentScan might need to be kept if it is for scanning some other classes.

Difference between CrudRepository and JpaRepository in Spring Data JPA

This article explains the differences between the Spring Data JPA CrudRepository and JpaRepository interfaces. Both of them can be used as the parent interface for our repositories, but they are not the same.

Background

Before we jump into the differences, it’s good to know why are we using these interfaces in the first place. There are two reasons for that:

  1. Extending these interfaces allows Spring to find your repository interfaces and create proxy objects for them, that you can inject later on into your beans.
  2. It provides you with methods that allow you to perform some common operations without the need to declare these methods yourself.

Differences

When talking about the differences of CrudRepository and JpaRepository, it is a good idea to take a third interface into account: the PagingAndSortingRepository. This is because these interfaces the following inheritance hierarchy between them:

  1. PagingAndSortingRepository extends CrudRepository
  2. JpaRepository extends PagingAndSortingRepository

The CrudRepository interface provides methods for CRUD operations, so it allows you to create, read, update and delete records without having to define your own methods. The PagingAndSortingRepository provides additional methods to retrieve entities using pagination and sorting. Finally the JpaRepository add some more functionality that is specific to JPA.

Generally the best idea is to use CrudRepository or PagingAndSortingRepository depending on whether you need sorting and paging or not. The JpaRepository should be avoided if possible, because it ties you repositories to the JPA persistence technology, and in most cases you probably wouldn’t even use the extra methods provided by it.