Is it okay to Autowire multiple repositories into another repository in Spring Data JPA?

Viewed 490

Is it okay to autowire multiple repositories (JPA interface) into another repository (class) as shown below

@Repository
public class repositoryClass {
@Autowired
private Repository1 repo1;
@Autowired
private Repository2 repo2;
}

Here repository 1 and 2 are Spring Data JpaRepository interfaces

The purpose of the repositoryClass is to fetch the sql queries from the repository1 and repository2 and then execute them using hibernate, because of that I am autowiring the repo1 and repo2 into the repositoryClass

3 Answers

It's bad design. In addition to breaking many of the principles of SOLID this results in a very high coupling. Let's start by reviewing what repositories are made for:

The repository pattern is pretty simple. An interface defines the repository with all logical read and write operations for a specific entity (e.g User).

We can conclude from this that repositories have one and only one responsibility which is CRUD's operations on specific entities. Then, based on the SRP principle, the reason to change the repository implementation is when the mapped entity changes (e.g we added new column to our user table and we want to acquire it from database) or we want to add some new function's to perform more CRUD operations (on the mapped entity!).

diagrams

Look at diagram1, if you want to change something in repository4, you have to change repository3, repository2 and repository1, so SRP principle is broken. It is an architectural disaster. This is due to the very high coupling between the different repositories. Now let's consider other design shown in diagram 2. Adapters are used to perform certain more complex operations using several repositories and to separate the application business layer from the data layer. If something changes in repository4 we will have to change SomeAdapterB however this will not affect the business logic as the adapter is a kind of gateway to the application.

In summary do not make repositories dependent on each other. Use adapters.

PS When you autowire dependencies in spring use constructor injection!

From Microsoft web site

The Repository pattern is a well-documented way of working with a data source. In the book Patterns of Enterprise Application Architecture, Martin Fowler describes a repository as follows:

A repository performs the tasks of an intermediary between the domain model layers and data mapping, acting in a similar way to a set of domain objects in memory. Client objects declaratively build queries and send them to the repositories for answers. Conceptually, a repository encapsulates a set of objects stored in the database and operations that can be performed on them, providing a way that is closer to the persistence layer. Repositories, also, support the purpose of separating, clearly and in one direction, the dependency between the work domain and the data allocation or mapping.

Here the most interesting part in my point of view, is the last sentence. The role of a design pattern (the Repository Pattern in this case) is to make things simple by providing a proven solution. By doing as shown in your code, you are violating many principles such as separation of concerns, single responsability principle and interface segregation.

Keep things simple as possible.

It is fine to add multiple repository in the one class say master repository.

@Repository
public class MasterRepository {
    @Autowired
    private Repository1 repo1;
    @Autowired
    private Repository2 repo2;
}

The benefit you will get that you don't need to add every repository in every classes where you are using. You just autowired masterrepository and use that.

Related