Hibernate - 如何在保持@ManyToOne关联的良好吞吐量的同时避免n + 1问题?

时间:2017-07-05 12:51:59

标签: java hibernate design-patterns hibernate-annotations

我有一个班级Entry,其中包含两个用于审核目的的字段:startAuditActionendAuditAction。一个审核操作可能会影响多个条目,因此类Entry描述ManyToOne关系如下:

public class Entry{
    @Id
    @Column(nullable = false)
    protected String path;

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false, name = "start_action_id")
    protected AuditAction startAction;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(updatable = true, nullable = true, name = "end_action_id")
    protected AuditAction endAction;
}

我想根据path字段和审核字段中的条件检索Entry实例。例如,要检索尚未删除的条目,HQL看起来应该是这样的:

SELECT DISTINCT entry FROM ENTRY_TABLE entry JOIN FETCH entry.startAction startAct LEFT JOIN FETCH entry.endAction endAct WHERE entry.path LIKE myPath and endAct IS NULL

我正在使用延迟加载JOIN FETCH来避免N + 1问题,同时仍然可以访问审计字段。但是,我有两个问题:

  • 首先,这对我来说似乎并不干净:如果我知道我想访问审计字段(即审计操作时间戳),那么它们不应该是延迟加载的。但是,如果我使用急切加载,即使我使用JOIN FETCH,我也面临着n + 1问题(在这种情况下,我不明白为什么fetch = FetchType.EAGER会有用)...
  • 其次,即使我避免了n + 1问题并因此减少了SQL查询,我的数据库整体使用也会遇到一些性能问题,可能是因为连接问题。

在保持良好吞吐量的同时避免触发其他查询的正确方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

1-如果您知道在特定情况下需要的字段中有FetchType.LAZY,则使用联接提取很有用,而使用FetchType.EAGER会强制该实体始终独立于查询

(例如,使用相同的配置示例,您可以执行多个查询,并且只有在需要集合时才使用JOIN FETCH

2-你可能在其他地方遇到问题,我怀疑加入会减慢你的速度