Hibernate很多人渴望获取N + 1

时间:2014-05-07 14:32:17

标签: java hibernate jpa

我有以下JPA实体:

@Entity
@Table(name = "app")
public class App {

    @Id
    private String id;

    @OneToOne(mappedBy = "app")
    @PrimaryKeyJoinColumn
    private FileDetails fileDetails;

    @ManyToOne
    private Developer developer;

    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;

    @OneToMany(mappedBy = "app", fetch = FetchType.EAGER)
    private List<Image> images;

    //getters, setters
}

如您所见,Image实体设置为EAGER抓取。 我想使用分页选择所有实体,我的Generic DAO使用此方法:

public List<T> findByPage(int pageNum, int pageSize) {
        CriteriaQuery<T> cq = getEntityManager()
                .getCriteriaBuilder().createQuery(entity);
        cq.select(cq.from(entity));

        int firstResult = pageNum * pageSize;
        return getEntityManager().createQuery(cq)
                .setFirstResult(firstResult)
                .setMaxResults(pageSize)
                .getResultList();
}

然而,当我运行查询时,我有一个与Image实体相关的N + 1。因此,对于每个选择的应用程序,我得到N个选择图像的数量。 Isnt EAGER抓取应该解决这个问题吗?什么可以解决?

1 个答案:

答案 0 :(得分:1)

IIRC,该查询中的joinfetch)到Image可以解决此类问题。

现在,由于您需要指定Image类,我将向您展示一个非通用解决方案,以便您验证它是否有效。

// notice I changed all <T> to <App>
public List<App> findByPage(int pageNum, int pageSize) {
        CriteriaQuery<App> cq = getEntityManager()
                .getCriteriaBuilder().createQuery(entity);

        Root<App> root = query.from(App.class); // added this
        root.fetch("app");                      // added this, this is the join

        cq.select(cq.from(entity));

        int firstResult = pageNum * pageSize;
        return getEntityManager().createQuery(cq)
                .setFirstResult(firstResult)
                .setMaxResults(pageSize)
                .getResultList();
}

我不是百分之百(我没有测试过,也不知道"app"字符串是否正确 - 它应该是你想要“拉”的字段,但由于这是多对一,我不确定,并将字段放在引用Image的{​​{1}}中,但我认为解决方案位于App左右,希望这指向了正确的方向。