java—在双向多对多关系中高效地获取子/父实体

xam8gpfp  于 2021-06-19  发布在  Mysql
关注(0)|答案(1)|浏览(352)

我正在开发一个使用mysql数据库的springboot服务。
我的数据库中有三个表:person、recipient和category。人和类别有双向的多对多关系,接受者也是。集合被延迟加载。
在控制器中,我想概述一下这三个表中的实体。我在服务层的代码如下所示:

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
    }
}

在前三行中,所有必需的实体在三个数据库查询中从数据库加载一次。从性能的Angular 来看,这是可以的。但是:
根据日志,打电话时。

Set<Category> categories = person.getCategories()

在第一个outer for循环中,服务进行另一个数据库查询来获取每个人的类别,尽管类别已经在前三个代码行中加载。其他循环也是如此。
例如,如果数据库中有5个人、6个收件人和7个类别,则服务总共执行3+5+6+2*7=28个数据库查询。显然,这是非常低效的。
我的问题是:
我必须做些什么更改,以便服务只获取每个实体一次,并尽可能少地进行数据库查询?

dw1jzc5e

dw1jzc5e1#

您面临的问题是典型的hibernate n+1问题。您可以急切地获取集合并编写自己的查询。

@Query("Select p from Person p join fetch p.categories categories)
public List<Person> fetchAllPerson();

您可以阅读更多关于它的jpa hibernate n+1问题(lazy&eager diff)

相关问题