4

我正在开发一个项目,该项目具有丰富的对象模型和各种聚合根集。

我们正在使用Castle堆栈(通过 ActiveRecord 到 nHibernate 的 Monorail)。

我们已将聚合根标记为惰性[ActiveRecord(Lazy = true)],并在我们的存储库上自定义了“渴望”例程以渴望获取对象图。我们使用 HQL 从我们的根的子集合中定义渴望获取,

例如,如果Account是聚合根(并标记为延迟加载),我们将急切地获取Account .. Order .. Product实体以获得完整的图形。

所以到目前为止没有任何意外(希望如此)。

现在,如果在上面的示例中, Product 也被标记[ActiveRecord(Lazy = true)],这似乎停止了 HQL 中的 Eager fetch 指令。

有谁知道强制急切获取延迟加载的子对象的方法

干杯伊恩

更新

好的,这里有一些示例 hql,使用下面 'me.yahoo.com/../1' 中的示例,我们在获取多对多关系时使用 IMuliQuery 来解决 N+1 依赖关系。我们还明确地使用了多对多映射类。因此,我们的 hql 是:

from Account a 'm eager loading the graph
inner join fetch a.AccountsOrders ao 
inner join fetch ao.Order
from Account a 'm eager loading the graph
inner join fetch a.AccountAddresses aa
inner join fetch aa.Address ad
where a.ID = ?

...所以这会执行 2 条 sql 语句并返回所需的最小行集,我们可以将其解析为单个对象图。好的。

但是...如果,比如说,Address被标记为延迟加载(并且Order没有),访问Order不会触发进一步的 sql 语句,但访问Address会触发,尽管事实上两者都是急切加载的。

那么为什么上面的延迟加载的实体没有Address被上面的语句急切地获取呢?

4

3 回答 3

1

对 Account.Order.Product 实体执行“内部连接提取”。所以不要像这样(这可能是你已经拥有的):

"from Account a inner join fetch a.Order where a.ID = ?"

告诉它也获取 Order.Product:

"from Account a inner join fetch a.Order inner join fetch a.Order.Product where a.ID = ?"
于 2008-12-19T19:55:41.717 回答
0

你为什么想要急切的行为?

ActiveRecord 中的所有关系属性都有一个“Lazy=”参数来告诉 ActiveRecord 延迟加载相关对象。除了 BelongsTo 之外的所有内容。BelongsTo 检查依赖对象的 ActiveRecord 属性中是否有 Lazy=true,然后为该对象创建一个代理,而不是执行选择或连接。

为了使延迟加载起作用,类实例的所有方法和属性都需要标记为虚拟。这允许 ActiveRecord 构造一个动态代理类。

现在,获取完整的性能图表可能听起来是个好主意,但实际上它可能会更慢。我有 3 个很好的理由:

1.) BelongsTo 有一个 Fetch 选项来定义如何拉取相关对象。FetchEnum.Join 强制 AR 使用 Join。获取枚举。Select 强制 AR 对每个对象使用单独的 select 语句。连接很慢,我们看到从切换到单个选择的性能提高了 10 倍。Lazy=true + FetchEnum.Select 和 eager 之间的客户端代码没有有效的区别。

2.) NHibernate 进行缓存。如果对象已经缓存在会话中或二级缓存中,则可以从那里加载它并避免额外的工作。

3.) 如果您没有引用对象图的一部分,您将错过延迟加载的任何好处。同样,您会做比必要更多的工作。

于 2009-02-13T20:41:55.910 回答
0

来自“NHibernate in Action”,第 225 页:

NHibernate 当前限制您只急切地获取一个集合。

这可能解释了获取地址的第二个查询。

于 2009-06-17T12:45:49.483 回答