NHibernate 特定映射(“使用祖父母选择”)
Posted
技术标签:
【中文标题】NHibernate 特定映射(“使用祖父母选择”)【英文标题】:NHibernate specific mapping ("select using grand-parent") 【发布时间】:2015-11-04 18:01:52 【问题描述】:我有这样的域结构(例如,伪代码):
class Room
Id: long
Shelves: list of Shelf
class Shelf
Id: long
Room: Room class (room_id column)
Books: list of Book
class Book
Id: long (id column)
Shelf: Shelf class (shelf_id column)
Room: Room class (room_id column)
Title: string (title column)
每个集合都是惰性的。 我想知道当我以惰性方式访问 Shelf's Books 属性时,是否有办法获取房间的所有书籍(没有子选择)。
当我得到 Room 时,nhibernate 只获取房间 (select * from rooms r where ...
),当我访问 Shelves 属性时,nhibernate 获取这个房间的所有书架 (select * from shelves s where s.room_id = X
),当我访问 Books 属性时,它为唯一一个书架加载书籍(一般情况下是正常的),但是......
在我的情况下,如果我访问 Book,我很有可能也会与这个房间的其他书籍一起工作,所以如果我触摸 book,我想预加载这个房间的所有书籍并将它们放在他们的书架上。
最接近nhibernate的特性是fetch='subselect'
。但是在我的情况下没有必要的选择,因为我可以通过 room_id 为这个房间取书:select * from books b where b.room_id = x
。
有没有办法做到这一点?
谢谢!
【问题讨论】:
【参考方案1】:NHibernate 内置的原生方式称为 Batch Fetching:
19.1.5. Using batch fetching
NHibernate 可以有效地利用批量获取,也就是说,如果访问一个代理(或集合),NHibernate 可以加载多个未初始化的代理。批量获取是对惰性选择获取策略的优化。有两种方法可以调整批量获取:在类和集合级别。
更多细节(上面的文档链接除外)可以在这里找到:
How to Eager Load Associations without duplication in NHibernate? NHibernate Fetch/FetchMany duplication in resultset, how to fix with ToFuture() How to eager load objects in a list/collection?【讨论】:
【参考方案2】:我找到了一个更优雅的解决方案。事实证明我可以为包/地图定义 sql-query...
看起来像:
<hibernate-mapping...>
<class name="Shelf">
<many-to-one name="Room" column="room_id"... />
<bag name="Books">
...
<loader query-ref="ShelvesQuery" />
</bag>
</class>
<sql-query name="ShelvesQuery">
<load-collection alias="book" role="Shelf.Books" />
<![CDATA[
select b.id
b.room_id,
b.shelf_id,
b.title
from books b
where b.room_id = :room_id
]]>
</sql-query>
</hibernate-mapping>
它就像一个魅力!
【讨论】:
以上是关于NHibernate 特定映射(“使用祖父母选择”)的主要内容,如果未能解决你的问题,请参考以下文章
NHibernate 是不是支持使用复合 ID 将抽象类映射到不同的表?
Fluent NHibernate 复合映射 <long, string>