为什么Hibernate(JPA)忽略了ManyToOne关系的FetchType.LAZY?

时间:2015-08-07 07:42:25

标签: java hibernate jpa many-to-one

我有这个实体,我想要一个多对一的关系,加载懒惰。

@Entity
public class Product {
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "atc_code_id")
    private ATCCode atcCode;
}

@Entity
public class ATCCode {
    @OneToMany(mappedBy = "atcCode")
    private Set<Product> products;
}

我正在使用此代码加载产品:

Query q = entityManager.createQuery("select p from Product as p");
List<Product> products = q.getResultList();

从休眠日志的第二行开始,我可以看到发出第二个select来初始化atcCode的proxoy。为什么呢?

17925 07 Aug 2015 11:45:20 SQL DEBUG 352066 kb - select product0_.id ...
17926 07 Aug 2015 11:45:20 Loader DEBUG 348515 kb - Result set row: 0
17927 07 Aug 2015 11:45:20 Loader DEBUG 348515 kb - Result row: EntityKey[com.galexis.search.importer.search.searchdb.model.Product#1]
17928 07 Aug 2015 11:45:20 Loader DEBUG 348515 kb - Result set row: 1
17929 07 Aug 2015 11:45:20 Loader DEBUG 348515 kb - Result row: EntityKey[com.galexis.search.importer.search.searchdb.model.Product#2]
17929 07 Aug 2015 11:45:20 TwoPhaseLoad DEBUG 348515 kb - Resolving associations for [com.galexis.search.importer.search.searchdb.model.Product#1]
17931 07 Aug 2015 11:45:20 TwoPhaseLoad DEBUG 348515 kb - Done materializing entity [com.galexis.search.importer.search.searchdb.model.Product#1]
17931 07 Aug 2015 11:45:20 TwoPhaseLoad DEBUG 348515 kb - Resolving associations for [com.galexis.search.importer.search.searchdb.model.Product#2]
17931 07 Aug 2015 11:45:20 TwoPhaseLoad DEBUG 348515 kb - Done materializing entity [com.galexis.search.importer.search.searchdb.model.Product#2]
17931 07 Aug 2015 11:45:20 SessionImpl DEBUG 348515 kb - Initializing proxy: [com.galexis.search.importer.search.searchdb.model.ATCCode#100]
17931 07 Aug 2015 11:45:20 SQL DEBUG 348515 kb - select atccode0_.id  ...

我的期望是返回atcCode的代理。只要我不访问atcCode,就不应该从DB加载它。

为什么hibernate初始化代理的想法?

这是对问题的解释。实际上,我在产品上有许多多对一的关系。所有这些都被宣布为懒惰。但由于它们实际上是笨拙地加载,我得到了很大的选择N + 1性能损失。

1 个答案:

答案 0 :(得分:0)

经过大量搜索后,我最终在org.hibernate.internal.SessionImpl中设置了一个断点,其中生成了日志语句Initializing proxy:。在堆栈跟踪中,我终于在Product中找到了这个:

@PostLoad
public void postLoad() {
    atcCode.getCode();
}

这会导致hibernate初始化代理。