我正在开发一个具有丰富对象模型的项目,该模型具有各种聚合根集合。
我们正在使用 Castle 堆栈(使用ActiveRecord的Monorail到nHibernate)。
我们已将聚合根标记为惰性[ActiveRecord(Lazy = true)]
,并在我们的存储库上定制了'eager'例程以急切获取对象图。我们使用HQL从我们的root的子集合
e.g。如果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语句,但访问{ {1}}尽管事实上两者都是渴望加载的。
那么为什么上述延迟加载的实体Address
不会被上述语句提取?
答案 0 :(得分: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 = ?"
答案 1 :(得分:0)
为什么你想要急切的行为?
ActiveRecord中的所有关系属性都有一个'Lazy ='参数,告诉ActiveRecord延迟加载相关对象。所有除了BelongsTo。 BelongsTo检查依赖对象的ActiveRecord属性是否具有Lazy = true,然后为该对象创建代理,而不是进行选择或连接。
对于延迟加载工作,需要将类实例的所有方法和属性标记为虚拟。这允许ActiveRecord构造动态代理类。
现在,获取完整的性能图可能听起来不错,但实际上它可能更慢。我有三个很好的理由:
1。)BelongsTo有一个Fetch选项来定义相关对象的拉取方式。 FetchEnum.Join强制AR使用Join。 FetchEnum。选择强制AR为每个对象使用单独的select语句。连接速度很慢,我们认为从切换到单个选择可以提高10倍的性能。 Lazy = true + FetchEnum.Select和eager之间的客户端代码没有任何有效差异。
2。)NHibernate进行缓存。如果对象已经缓存在会话或二级缓存中,则可以从那里加载它,避免额外的工作。
3。)如果你没有引用对象图的一部分,你会错过延迟加载的任何好处。你会再做更多的工作。
答案 2 :(得分:0)
来自“NHibernate in Action”,第225页:
NHibernate目前限制你急切地抓取一个集合。
这可能解释了获取地址的第二个查询。