I am developing a SpringBoot service which uses a mysql database.
There are three tables in my database: Person, Recipient and Category. Person has a bidirectional many-to-many relationship to Category and so does Recipient. Collections are loaded lazily.
In a controller, I want to give an overview about the entities in these three tables. My code in the service layer looks like this:
List<Person> allPersons = personRepository.findAll();
List<Recipient> allRecipients = recipientRepository.findAll();
List<Category> allCategories = categoryRepository.findAll();
for(Person person : allPersons){
Set<Category> categories = person.getCategories();
for(Category category : categories){
// do something with the person and the categories
}
}
for(Recipient recipient : allRecipients){
Set<Category> categories = recipient.getCategories();
for(Category category : categories){
// do something with the recipient and the categories
}
}
for(Category category : allCategories){
Set<Person> persons = category.getPersons();
for(Person person : persons){
// do something with the category and the persons
}
Set<Recipient> recipients = category.getRecipients();
for(Recipient recipient : recipients){
// do something with the category and the recipients
}
}
Within the first three lines, all necessary entities are loaded from the database exactly once within three database queries. This is OK from a performance point of view. But:
According to the logs, while calling e.g.
Set<Category> categories = person.getCategories()
in the first outer for-loop, the service makes another database query to fetch the person's categories for each person, although the categories have already been loaded within the first three code lines. The same holds for the other loops.
For example, if there are 5 persons, 6 recipients and 7 categories within the database, the service performs 3 + 5 + 6 + 2*7 = 28 database queries in total. Obviously, this is very inefficient.
My question is:
What do I have to change so that the service fetches each entity only once with as few database queries as possible?