How can we test for the N+1 problem in JPA/Hibernate?

一个人想着一个人 提交于 2020-03-04 06:05:11

问题


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?


回答1:


As option you can verify count of queries (fetch, updates, inserts) in the test

 repository.findById(10L);

 SessionFactory sf = em.getEntityManagerFactory().unwrap(SessionFactory.class);
 Statistics statistics = sf.getStatistics();

 assertEquals(2L, statistics.getQueryExecutionCount());

See hibernate statistic




回答2:


Refer to following solution, which relies on wrapping your DataSource https://vladmihalcea.com/how-to-detect-the-n-plus-one-query-problem-during-testing/




回答3:


I suppose by "regression test" you mean an actual test probably started by JUnit.

A general way to handle that in a Unit-Test could be:

  • configure hibernate.show_sql to true
  • intercept the log-messages like described in intercept.
  • scan the log-file for
    • specific queries, you want to be avoided
    • number of similar queries


来源:https://stackoverflow.com/questions/55872771/how-can-we-test-for-the-n1-problem-in-jpa-hibernate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!