I have a N+1 problem, and I’d like to write some kind of automated regression test because it impacts performance very much.
I thought about spying the EntityManager and verifying its method createQuery()
is called only once, but Hibernate don’t use it to initialize lazy relationships, thus it didn’t work. I could also try to shut down the JPA transaction between my repository and my service (or detach my entity) and look out for exceptions, but it’s really an ugly idea.
To give us a frame, let’s say we have a very simple parent-child model:
@Entity
public class Parent {
…
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
private Collection<Child> children;
}
@Entity
public class Child {
…
@ManyToOne
private Parent parent;
}
And a very simple service:
public class MyService {
…
public void doSomething(Long parentId) {
Parent parent = …; /* retrieve Parent from the database */
doSomeOtherThing(parent.getChildren());
}
}
Parent retrieval from database could use the two following queries:
SELECT parent FROM Parent parent WHERE parent.id = :id;
SELECT parent FROM Parent parent JOIN FETCH parent.children WHERE parent.id = :id;
How may I write a test that crashes when I retrieve my Parent entity with the first query, but not the second?
getChildren()
actually returns aPersistentCollection
and if so whetherwasInitialized()
returns true or not. If that persistent collection is not initialized then any access is likely to cause lazy loading (there might be cases where this doesn't happen, e.g. when callingsize()
and depending on your mapping - e.g. whether it is extra lazy or not, but it is very likely). – Kana