4

In "getting started" examples of Spring Data JPA, we create an interface which extends CrudRepository. However it handles only one Entity:

import org.springframework.data.repository.CrudRepository;

interface MyEntityRepository extends CrudRepository<MyEntity, Long> {
  // methods...
}

In a real world application, there are many Entities (tables) and we need to do CRUD operations for them. What is the correct way to use Spring Data JPA repositories with multiple (related or unrelated) Entities?

Do I have to create interfaces for each Entities and Autowire them one by one (Which sounds very crazy idea for now)?

Oliver Drotbohm
  • 71,632
  • 16
  • 205
  • 196
Yasin Okumuş
  • 1,931
  • 5
  • 27
  • 54
  • 1
    Yes you are right with "Do I have to create interfaces for each Entities and Autowire them one by one". but you have to create an repository for all tables where you need to do SQL operations on. – Jens Sep 08 '15 at 18:28
  • Thanks @Jens but if I have 10 entities, isn't it odd to create 10 interfaces and autowire them to use? What is the correct way to do this? Is there any other class or interface to sum up them all? – Yasin Okumuş Sep 08 '15 at 18:35
  • Possible duplicate of [Are you supposed to have one repository per table in JPA?](https://stackoverflow.com/questions/21265262/are-you-supposed-to-have-one-repository-per-table-in-jpa) – Jens Schauder Sep 21 '18 at 06:33

2 Answers2

14

Spring Data use the concept of repositories as defined in Domain Driven Design. Repositories basically represent a collection of aggregate roots, which in turn are some of your entities, that you'll access and which enforce business constraints on others. E.g. if you have an Order consisting of LineItems, the Order'd be the aggregate root as it controls the lifecycle of the LineItems etc. Hence you'd define a repository for the Order but not for the LineItem. So it's by far not all entities that you'd create repositories for. It's basically an important part in your domain modeling to decide which entities become aggregate roots.

Another aspect is that repositories are usually backed by a persistence mechanism and that you don't want to code your business logic directly to the persistence API to keep it testable without having to deal with the persistence API. That means, a repository will contain query methods that basically represent a subset of all aggregate roots in the collection and are backed by a store-specific query implementation. This can only be achieved in a by-aggregate-root fashion.

The third and final aspect is that repositories help you to restrict access to persistence operations more easily as you can use e.g. the package scope to force clients to even use a dedicated service and basically hide all persistence operation for a certain domain object in a certain package. With a generic persistence API like the EntityManager you lose control over who actually reads what from any point in the system as it can just persist each and every type in the persistence context.

To summarize things: repositories represent a collection of aggregates and allow access to dedicated subsets of that collection. Spring Data makes creating these as easy as possible with the alternatives being architecturally less desirable (see reasoning above) or more cumbersome (if they had to be implemented manually. For which entities you create repositories depends on how you model your domain, which of them are aggregate roots.

Oliver Drotbohm
  • 71,632
  • 16
  • 205
  • 196
  • Thank you very much. So still I understand this: I have #N number of entities, so I have to create #N number of repository internfaces and put them one by one to the Service beans or other beans as @Autowired. I still can't understand the meaning of this: 100 repository internfaces for 100 entities and 100 autowired beans. – Yasin Okumuş Sep 12 '15 at 21:43
  • Yes, I did, maybe three times. Reading again and I understand that domain driven design makes us force such architecture. I read your other answer for the same question: http://stackoverflow.com/a/21277087/169534 If I misunderstand, that means there is a way to do that. What is it? – Yasin Okumuş Sep 13 '15 at 13:32
4

You are correct. For each entity you want to use Spring Data with, you need to create an interface that extends one of the repository interfaces and then autowire that interface into your classes. You only need one of these per entity you wish to perform crud/query operations on. If there is an entity contained within another entity that is created/managed via a cascade relationship, you don't need to explicitly create a repository for that entity.

To your point, it may seem slightly verbose to have to create an interface and autowire it for each entity, but that's the way Spring Data was designed and is what enables it to automatically generate data access code for you. You obviously wouldn't have to do that if you wanted to write your own data layer.

Chris Thompson
  • 33,380
  • 11
  • 76
  • 105