在我搜索之后,我找不到任何有用的东西来帮助我弄清楚从哪里开始。
到目前为止,我只编写了相当简单的nHibernate查询,并且有一个相对复杂的SQL,我需要在QueryOver(Icriteria)中进行抽取,或者如果证明它过于繁琐,那就是HQL。请在下面找到查询:
Select aliasTable1.Id, AliasTable1.Time,
AlaisTable2.Version,
(select top 1 secondAliasTable1.Time
from Table1 secondAliasTable1
where aliasTable1.Time < secondAliasTable1.Time
AND secondAliasTable1.Time < (SELECT Top 1 thirdAliasTable1.Time from Table1 thirdAliasTable1
where thirdAliasTable1.Name = 'stringValue1'
AND thirdAliasTable1.Id = aliasTable1.Id
AND thirdAliasTable1.Time > aliasTable1.Time
ORDER By thirdAliasTable1.Time)
AND secondAliasTable1.Name = 'stringValue2'
AND secondAliasTable1.Id = aliasTable1.Id
ORDER BY secondAliasTable1.Time) As 'Endtime'
from Table1 aliasTable1
INNER JOIN Table2 aliasTable2 on AliasTable2.Id = aliasTable1.table2Id
where alaisTable1.Name = 'stringValue2'
ORDER BY alaisTable1.Time
在转换过程中,我确实遇到了这个查询,所以我希望至少得到一个起点让我走,如果不是一个完整的答案!
干杯
答案 0 :(得分:4)
这在很大程度上取决于你的映射,但是这样的事情应该有效:
Table1 aliasTable1 = null, secondAliasTable1 = null, thirdAliasTable1 = null;
Table2 aliasTable2 = null;
var result = session.QueryOver<Table1>(() => aliasTable1)
.Where(p => p.Name == "stringValue1")
.JoinQueryOver(p => p.Table2, () => aliasTable2)
.SelectList(list => list
.Select(() => aliasTable1.Id)
.Select(() => aliasTable1.Time)
.Select(() => aliasTable2.Version)
.SelectSubQuery(
QueryOver.Of<Table1>(() => secondAliasTable1)
.Where(() => aliasTable1.Time < secondAliasTable1.Time)
.WithSubquery.Where(() => secondAliasTable1.Time <
QueryOver.Of<Table1>(() => thirdAliasTable1)
.Where(() => thirdAliasTable1.Name == "stringValue1")
.And(() => thirdAliasTable1.Id == aliasTable1.Id)
.And(() => thirdAliasTable1.Time > aliasTable1.Time)
.SelectList(inner => inner
.Select(() => thirdAliasTable1.Time))
.OrderBy(() => thirdAliasTable1.Time).Asc()
.Take(1)
.As<DateTime>())
.And(() => secondAliasTable1.Name == "stringValue2")
.And(() => secondAliasTable1.Id == aliasTable1.Id)
.SelectList(third => third
.Select(() => secondAliasTable1.Time))
.OrderBy(() => secondAliasTable1.Time).Asc()
.Take(1)))
.OrderBy(() => aliasTable1.Time).Asc()
.List<object[]>();
这会生成如下所示的SQL:
SELECT this_.Id as y0_,
this_.Time as y1_,
aliastable1_.Version as y2_,
(SELECT TOP (1 /* @p0 */) this_0_.Time as y0_
FROM [Table1] this_0_
WHERE this_.Time < this_0_.Time
and this_0_.Time < (SELECT TOP (1 /* @p1 */) this_0_0_.Time as y0_
FROM [Table1] this_0_0_
WHERE this_0_0_.Name = 'stringValue1' /* @p2 */
and this_0_0_.Id = this_.Id
and this_0_0_.Time > this_.Time
ORDER BY this_0_0_.Time asc)
and this_0_.Name = 'stringValue2' /* @p3 */
and this_0_.Id = this_.Id
ORDER BY this_0_.Time asc) as y3_
FROM [Table1] this_
inner join [Table2] aliastable1_
on this_.Id = aliastable1_.Table1Id
WHERE this_.Name = 'stringValue1' /* @p4 */
ORDER BY this_.Time asc
您可以投放到您选择的DTO(使用.List<object[]>()
),而不是TransformUsing
。如果这看起来势不可挡,我强烈建议将每个分离的QueryOver
分解为它自己的变量,然后从主查询中引用它们。
更新:如果您想使用.TransformUsing
,则需要创建null
结果对象并使用.WithAlias()
:
Table1 aliasTable1 = null, secondAliasTable1 = null, thirdAliasTable1 = null;
Table2 aliasTable2 = null;
MyDTO dto = null;
var result = session.QueryOver<Table1>(() => aliasTable1)
.Where(p => p.Name == "stringValue1")
.JoinQueryOver(p => p.Table2, () => aliasTable2)
.SelectList(list => list
.Select(() => aliasTable1.Id).WithAlias(() => dto.Id)
.Select(() => aliasTable1.Time).WithAlias(() => dto.Time)
.Select(() => aliasTable2.Version).WithAlias(() => dto.Version)
.SelectSubQuery(
QueryOver.Of<Table1>(() => secondAliasTable1)
.Where(() => aliasTable1.Time < secondAliasTable1.Time)
.WithSubquery.Where(() => secondAliasTable1.Time <
QueryOver.Of<Table1>(() => thirdAliasTable1)
.Where(() => thirdAliasTable1.Name == "stringValue1")
.And(() => thirdAliasTable1.Id == aliasTable1.Id)
.And(() => thirdAliasTable1.Time > aliasTable1.Time)
.SelectList(inner => inner
.Select(() => thirdAliasTable1.Time))
.OrderBy(() => thirdAliasTable1.Time).Asc()
.Take(1)
.As<DateTime>())
.And(() => secondAliasTable1.Name == "stringValue2")
.And(() => secondAliasTable1.Id == aliasTable1.Id)
.SelectList(third => third
.Select(() => secondAliasTable1.Time))
.OrderBy(() => secondAliasTable1.Time).Asc()
.Take(1)).WithAlias(() => dto.Time2))
.OrderBy(() => aliasTable1.Time).Asc()
.TransformUsing(Transformers.AliasToBean<MyDTO>())
.List<MyDTO>();
答案 1 :(得分:0)
使用HQL,假设您已将实体映射到表:
联接可以通过这种方式明确地完成:
Select aliasTable1.Id, aliasTable2.Version
from Table1 as aliasTable1
JOIN aliasTable1.table2 as aliasTable2;
另外,我不确定你是否可以在HQL中拥有Top in Inner Queries,所以你可以将它们更改为:
AND secondAliasTable1.Time < (SELECT max(thirdAliasTable1.Time) from Table1 as thirdAliasTable1
where thirdAliasTable1.Name = 'stringValue1'
AND thirdAliasTable1.Id = aliasTable1.Id
AND thirdAliasTable1.Time > aliasTable1.Time)
此外,如果您希望查询返回仅包含那4个属性(id,time,version和endTime)的DTO列表,您应该查看Transformers.aliasToBean()。
我曾在这里写过一些关于此的内容:http://hordine.com/?p=1187