当您执行未来查询时,您会将所有父对象和子对象拉入一级缓存。 Parent 对象包含一个需要填充的惰性集合。为了填充集合,NHibernate 必须查询数据库。 (我们马上就会知道原因。)查询返回子对象,而这些子对象已经在 L1 缓存中。所以这些对象用于填充集合。
现在为什么 NHibernate 必须查询数据库来填充 Childs 集合?您可以在集合上有一个“where”子句,用 IsDeleted==true 过滤掉子对象。您可以在过滤掉某些子对象的 EventListener 中有代码。基本上有很多事情会发生,NHibernate 不能对 Parent 和 Child 对象之间的关系做出任何假设。
您可以通过在 HQL 或映射中指定获取策略来为其提供足够的信息。在 HQL 中,你可以这样写:
var parents = session.CreateQuery("from Parent p join fetch p.Childs").Future<Parent>();
使用未来的子对象查询将是完全可选的,因为您要与父母一起获取孩子。由于连接提取,您将获得重复的 Parent 对象,尽管它们将是同一个对象。 (您正在数据库中进行内部连接,并为每个子行返回一个父行的副本。)您可以通过遍历 parents.Distinct() 来摆脱这些。
如果您总是想通过相应的 Parent 获取 Child 对象,您也可以在 Parent 映射中使用 fetch="join"。
<bag name="Children" cascade="all-delete-orphan" fetch="join">
<key column="ParentId"/>
<one-to-many class="Child"/>
</bag>
如果这些选项都不适用于您的方案,您可以在集合映射上指定批量大小。当您点击 parent.Childs 时,您仍然会执行数据库查询,但 NHibernate 会急切地初始化任何其他集合代理。
<bag name="Children" cascade="all-delete-orphan" batch-size="10">
<key column="ParentId"/>
<one-to-many class="Child"/>
</bag>