执行未来查询时,会将所有父对象和子对象拉入一级缓存。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>