在双向多对多关系中高效获取 child/parent 个实体
Efficient fetching of child/parent entities in a bidirectional many-to-many relationship
我正在开发一个使用 mysql 数据库的 SpringBoot 服务。
我的数据库中有三个表:Person、Recipient 和 Category。 Person 与 Category 具有双向多对多关系,Recipient 也是如此。集合延迟加载。
在控制器中,我想概述一下这三个表中的实体。我在服务层的代码如下所示:
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
}
}
在前三行中,所有必要的实体在三个数据库查询中恰好从数据库中加载一次。从性能的角度来看,这是可以的。但是:
根据日志,在调用时
Set<Category> categories = person.getCategories()
在第一个外部 for 循环中,服务进行另一个数据库查询以获取每个人的个人类别,尽管这些类别已在前三个代码行中加载。其他循环也是如此。
例如,如果数据库中有 5 个人、6 个收件人和 7 个类别,则该服务总共执行 3 + 5 + 6 + 2*7 = 28 次数据库查询。显然,这是非常低效的。
我的问题是:
我必须更改什么才能使服务仅使用尽可能少的数据库查询获取每个实体一次?
您面临的问题是典型的休眠 N+1 problem.You 可以急切地获取您的集合并编写您自己的查询。
@Query("Select p from Person p join fetch p.categories categories)
public List<Person> fetchAllPerson();
您可以阅读更多相关信息JPA Hibernate n+1 issue (Lazy & Eager Diff)
我正在开发一个使用 mysql 数据库的 SpringBoot 服务。
我的数据库中有三个表:Person、Recipient 和 Category。 Person 与 Category 具有双向多对多关系,Recipient 也是如此。集合延迟加载。
在控制器中,我想概述一下这三个表中的实体。我在服务层的代码如下所示:
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
}
}
在前三行中,所有必要的实体在三个数据库查询中恰好从数据库中加载一次。从性能的角度来看,这是可以的。但是:
根据日志,在调用时
Set<Category> categories = person.getCategories()
在第一个外部 for 循环中,服务进行另一个数据库查询以获取每个人的个人类别,尽管这些类别已在前三个代码行中加载。其他循环也是如此。
例如,如果数据库中有 5 个人、6 个收件人和 7 个类别,则该服务总共执行 3 + 5 + 6 + 2*7 = 28 次数据库查询。显然,这是非常低效的。
我的问题是:
我必须更改什么才能使服务仅使用尽可能少的数据库查询获取每个实体一次?
您面临的问题是典型的休眠 N+1 problem.You 可以急切地获取您的集合并编写您自己的查询。
@Query("Select p from Person p join fetch p.categories categories)
public List<Person> fetchAllPerson();
您可以阅读更多相关信息JPA Hibernate n+1 issue (Lazy & Eager Diff)