优化NHibernate的SQL连接查询
以一个相当简单的域模型Orders、items和shipping为例,其中Order是根实体,shipping是根实体。我想查找给定订单的所有装运。这个问题很直截了当,但我看到了NHibernate的不良行为 模型 生成的装运对象是正确的,但查询加载的数据太多,因为我只对装运日期感兴趣。订单和行项目数据将立即丢弃,并且永远不会使用。我尝试过使用延迟加载以及我可以在网上找到的每一种获取策略,但我无法让它简单地返回基本数据 如何减少SQL查询中的噪音,使其仅加载装运数据和行项目的主键以支持延迟加载?更像这样:优化NHibernate的SQL连接查询,nhibernate,join,Nhibernate,Join,以一个相当简单的域模型Orders、items和shipping为例,其中Order是根实体,shipping是根实体。我想查找给定订单的所有装运。这个问题很直截了当,但我看到了NHibernate的不良行为 模型 生成的装运对象是正确的,但查询加载的数据太多,因为我只对装运日期感兴趣。订单和行项目数据将立即丢弃,并且永远不会使用。我尝试过使用延迟加载以及我可以在网上找到的每一种获取策略,但我无法让它简单地返回基本数据 如何减少SQL查询中的噪音,使其仅加载装运数据和行项目的主键以支持延迟加载?
SELECT this_.Id as Id5_2_,
this_.Date as Date5_2_,
this_.LineItem_id as LineItem3_5_2_,
lineitem1_.Id as Id4_0_,
FROM [Shipment] this_
inner outer join [LineItem] lineitem1_
on this_.LineItem_id = lineitem1_.Id
WHERE lineitem1_.Order_id = 1 /* @p0 */
自定义SQL查询更新
使用如下所示的自定义SQL查询可以获得所需的性能和正确的行为。然而,它有点违背了ORM的目的。为什么NHibernate不能生成这样一个简单的查询
Session
.CreateSQLQuery(
@"SELECT SH.*, LI.Id FROM Shipment SH
INNER JOIN LineItem LI ON LI.Id = SH.LineItem_id
WHERE LI.Order_id = ?" )
.SetInt32( 0, order.Id )
.List<Shipment>();
如果您只对日期感兴趣,而不是以select Shipping结束LINQ语句;,您可以选择Shipping.Date结束它;这样就不会返回完整的对象层次结构。如果你想要一些额外的细节,你可以创建一个匿名类型 var装运=来自会话.Linq中的装运,其中装运.LineItem.Order==订单
选择新建{Id=shipping.Id,Date=shipping.Date,LineItemId=shipping.LineItem.Id,OrderId=shipping.LineItem.Order.Id} 您可以向域模型订单类添加多对多关系。如果您使用的是nhibernate映射xml文件,那么可以通过向订单映射添加以下内容来实现
<bag name="Shipments" table="LineItem" lazy="true">
<key column="id"/>
<many-to-many class="Shipment" column="lineitem_id" />
</bag>
您应该能够在C中使用lamda表达式和新的对象初始值设定项 我已经有一段时间没有这样做了,因为我回到了旧式的2.0 我知道在linq你可以做到这一点,我不确定Nhibernate linq是否支持这一点
var shipments = from shipment in session.Linq<Shipment>()
where shipment.LineItem.Order == order
select(x => new Shipment { Date = x.Date } );
看看这个,它是用c编写的,但是在java站点上。这应该只执行一条语句,该语句将离开并选择订单等于指定订单的日期。但它会返回一个装运对象,只填充日期。根据进一步的研究和这里的帖子。答案是你不能:ooh这几乎奏效了。使用您的想法确实会产生一个更干净的查询,尽管它仍然有比所需更多的连接。然而,我确实需要实际的发货对象,因为实际的模型有点复杂。这是一个明显的解决方案,并且由于域的原因而不起作用。订单不负责发货。发货是发生在与订单完全不同的流程和服务中的事件。对于其他ORM中如此简单的事情,这似乎需要大量的工作。为什么我不能等到NHibernate生成一个更好、更简单的查询?我相信这是可能的,但我不完全确定如何做到这一点。以下三种方法是我开始尝试实现这一目标的地方。ISession.CreateCriteria ISession.CreateQuery ISession.CreateSqlQuery这是我能做的最好的了,我希望它能有所帮助。你能发布你的HBM文件吗?
Session
.CreateSQLQuery(
@"SELECT SH.*, LI.Id FROM Shipment SH
INNER JOIN LineItem LI ON LI.Id = SH.LineItem_id
WHERE LI.Order_id = ?" )
.SetInt32( 0, order.Id )
.List<Shipment>();
<bag name="Shipments" table="LineItem" lazy="true">
<key column="id"/>
<many-to-many class="Shipment" column="lineitem_id" />
</bag>
var shipments = from shipment in order.Shipments select shipment.Date;
var shipments = from shipment in session.Linq<Shipment>()
where shipment.LineItem.Order == order
select(x => new Shipment { Date = x.Date } );