在Nhibernate HQL中连接具有嵌套选择计数和分组的表

时间:2010-03-04 13:29:02

标签: nhibernate fluent-nhibernate hql

我有帖子,投票和评论表。每个帖子可以有N票和N条评论。我一直试图找到一种方法来使用Nhibernate HQL进行此查询但没有成功。

 SELECT P.Id, P.Title, P.TextDescription, ISNULL(V.TotalVotes,0), ISNULL(C.TotalComments, 0)
 FROM
 Post P

 LEFT JOIN
   (SELECT 
    PostId, count(PostId) as TotalVotes 
    FROM Vote 
    GROUP BY PostId) V
 ON V.PostId = P.Id 

 LEFT JOIN 
    (SELECT 
     PostId, count(PostId) as TotalComments
     FROM Comment 
     GROUP BY PostId) C
 ON C.PostId = P.id 

我将GROUP BY聚合推送到嵌套的SELECT语句中,因为我想只对PostId进行分组而不是所有其他列。我的域类:

后期属性:

int Id  { get; set; }
string Title { get; set; }
string TextDescription { get; set; }
IList<Comment> Comments { get; set; } -> HasMany
IList<Vote> Votes { get; set; } -> HasMany

评论 - 属性:

int Id  { get; set; }
Post Post { get; set; } -> reference

投票

int Id  { get; set; }
Post Post { get; set; } -> reference

我真的对此感到困惑。我希望我不会走错方向。也许我应该只使用Nhibernate公式属性,我可以为我的计数声明一个任意的SQL表达式。

非常感谢任何帮助..

谢谢!

2 个答案:

答案 0 :(得分:2)

对于您要执行的操作,您需要编写任何HQL查询 由于您的类中有集合,并且已将它们映射到.hbm.xml文件中(如果您使用的是流畅的nhibernate,请忽略它)

<bag name="Comments" inverse="true" lazy="extra">
    <key column="CommentId" />
    <one-to-many class="Comment,mylib" />
</bag>

<bag name="Votes" inverse="true" lazy="extra">
    <key column="VoteId" />
    <one-to-many class="Vote,mylib" />
</bag>

致电

Post post = ISession.Get<Post>(postId);

使用代理初始化CommentsVotes个集合。 当您触摸该集合时

post.Comments.Count

NHibernate将使用PostId postId在注释上触发选择计数(*)。

如果你绝对想用公式实现这个(因为你希望每次获取帖子时都能看到计数),你就不需要HQL(或那个问题的标准)查询

编辑: 由于您不需要公式并且想要在一次往返中获取结果,因此这里是HQL的解决方案(需要上面的集合映射)

IQuery query = nhSession.CreateQuery("select p, count(p.Comments), p.(p.Votes) from Post p where p.id = :postId");
query.SetInt32("postId", postId);
object result = query.UniqueResult();

其中result是一个数组(我认为是ArrayList),其中result [0]是Post类型对象,result [1]是注释计数(int / long),result [2]是投票计数(int / long) )

答案 1 :(得分:0)

如果使用lazy =“extra”映射集合,则其Count属性不会导致集合的加载。