休眠:n+1 和实体图性能降低



我们升级到Hibernate 5,之后我们开始遇到性能问题。

我们有几个实体具有这样的关联:

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

我们使用条件 API 从数据库中获取数据。

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();

以前(版本4,旧的标准API(,Hibernate生成了一个带有连接语句的选择,该连接语句仅基于FetchType.EAGER获取所有数据,但是在Hibernate 5中,它创建了多个额外的查询来获取"位置"数据 - N + 1问题。

现在,我们尝试了JPA实体图,结果好坏参半。我们能够减少查询数量(现在没有 N+1(,但另一方面,系统的性能甚至更慢。

我的问题是:

  1. 还有哪些其他方法可以消除 N+1 查询问题?
  2. 在什么情况下,实体图会对性能产生负面影响?

(我们使用SQL Server,Tomcat,Hibernate5.2.10,Java 8。

要获得fetching location data along with join in a single query的早期行为,可以通过添加fetch来实现

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

因此,您的代码将如下所示:

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();

最新更新