简体   繁体   中英

Hibernate: n+1 and slow performance with Entity Graph

We did an upgrade to Hibernate 5, after which we began to experience performance issues.

We have several entities with associations like this:

@Entity
@Table(name = "EVENT")
public class Event {
    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "LOCATION", referencedColumnName = "ID")
    private Location location;
}

@Entity
@Table(name = "LOCATION")
public class Location {
    @Id
    @Column(name = "ID")
    private Long id;
}

We are using the Criteria API to fetch the data from the database.

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Event> query = cb.createQuery(Event.class);
Root<Event> from = query.from(Event.class);
query.select(from).where(from.get("id").in(1, 2, 3));
TypedQuery<Event> tQuery = entityManager.createQuery(query);
tQuery.setMaxResults(1000);
tQuery.getResultList();

Previously (version 4, old Criteria API), Hibernate generated one select with a join statement that fetched all the data, just based on the FetchType.EAGER, but with Hibernate 5, it creates multiple additional queries for fetching the 'location' data - the N+1 problem.

Now, we have tried JPA Entity Graph, with mixed results. We were able to reduce the number of queries (no N+1 now), but on the other hand, the performance of the system is even slower.

My questions are:

  1. what other ways are there to remove N+1 queries problem?
  2. under what circumstances could Entity Graphs have negative performance impact?

(We use SQL Server, Tomcat, Hibernate 5.2.10, Java 8.)

To get the earlier behaviour of fetching location data along with join in a single query can be achieved by adding the fetch

from.fetch("location", javax.persistence.criteria.JoinType.LEFT);

So your code would look like:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Event> query = cb.createQuery(Event.class);
Root<Event> from = query.from(Event.class);
from.fetch("location", javax.persistence.criteria.JoinType.LEFT);
query.select(from).where(from.get("id").in(1, 2, 3));
TypedQuery<Event> tQuery = entityManager.createQuery(query);
tQuery.setMaxResults(1000);
tQuery.getResultList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM