У меня проблема с N + 1, и я хотел бы написать какой-нибудь автоматический регрессионный тест, потому что он очень сильно влияет на производительность.
Я думал о шпионаже EntityManager и проверке, что его метод createQuery()
вызывается только один раз, но Hibernate не использует его для инициализации ленивых отношений, поэтому он не работает. Я также мог бы попытаться закрыть транзакцию JPA между моим хранилищем и моим сервисом (или отсоединить мою сущность) и посмотреть на исключения, но это действительно ужасная идея.
Чтобы дать нам рамку, допустим, у нас есть очень простая модель родитель-потомок:
@Entity
public class Parent {
…
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
private Collection<Child> children;
}
@Entity
public class Child {
…
@ManyToOne
private Parent parent;
}
И очень простой сервис:
public class MyService {
…
public void doSomething(Long parentId) {
Parent parent = …; /* retrieve Parent from the database */
doSomeOtherThing(parent.getChildren());
}
}
Для родительского поиска из базы данных могут использоваться два следующих запроса:
SELECT parent FROM Parent parent WHERE parent.id = :id;
SELECT parent FROM Parent parent JOIN FETCH parent.children WHERE parent.id = :id;
Как мне написать тест, который дает сбой, когда я получаю родительский объект с первым запросом, но не со вторым?