【问题标题】:Nhibernate join filtering休眠连接过滤
【发布时间】:2011-09-26 18:09:45
【问题描述】:

我有一个关于加入 NHIBERNATE 的问题。我们的 sql 查询存在问题,该查询已生成但处于休眠状态。我们的 db 开发人员对原始 sql 进行了优化,因此它可以按我们的需要工作,但我们需要更改 nhibernate 代码以使生成的 sql 看起来像是经过优化的。

查询的原始部分是:

FROM   PERSON_VISIT this_
                     inner join PERSON_Basic per2_
                       on this_.PERSON_ID = per2_.PERSON_ID
                     left outer join PERSONC_QUESTIONS perint10_
                       on per2_.PERSON_ID = perint10_.PERSON_ID
                     left outer join TELEPHONE_QUESTIONS intaudit13_
                       on perint10_.PP_QUESTIONS_ID = intaudit13_.PP_QUESTIONS_ID
                     inner join C_QUESTIONS intdef14_
                       on perint10_.QUESTION_ID = intdef14_.QUESTION_ID
                          and perint10_.QUESTIONS_CODE = intdef14_.QUESTIONS_CODE
                          and perint10_.QUESTION_ID = intdef14_.QUESTION_ID

优化后的是:

FROM   PERSON_VISIT this_
                     inner join PERSON_Basic per2_
                       on this_.PERSON_ID = per2_.PERSON_ID
                     left outer join PERSONC_QUESTIONS perint10_
                       on per2_.PERSON_ID = perint10_.PERSON_ID
                     left outer join TELEPHONE_QUESTIONS intaudit13_
                       on perint10_.PP_QUESTIONS_ID = intaudit13_.PP_QUESTIONS_ID
                     left outer join C_QUESTIONS intdef14_
                       on perint10_.QUESTION_ID = intdef14_.QUESTION_ID
                          and perint10_.QUESTIONS_CODE = intdef14_.QUESTIONS_CODE
                          and perint10_.QUESTION_ID = intdef14_.QUESTION_ID
                          and intdef14_.DISCIPLINE_CODE = this_.DISCIPLINE_CODE

要将查询从内连接更改为左外连接很容易,我只更改了一行代码:

        .CreateAlias("PersonInt.QuestionEntity", "IntDef", JoinType.LeftOuterJoin)

但是我该如何添加

                          and intdef14_.DISCIPLINE_CODE = this_.DISCIPLINE_CODE

使用休眠代码?

有一个选项可以将 PERSON_VISIT 定义中的引用添加到 C_QUESTIONS,但问题是 PERSON_VISIT 无处不在,我不希望这个更改可能破坏其他查询,我只想添加一行代码来添加,我该怎么做?有什么办法可以访问原始联接来更改它?或者其他方式来添加这个

                          and intdef14_.DISCIPLINE_CODE = this_.DISCIPLINE_CODE

要查询吗? 我知道有人会说我们可以通过条件为查询添加限制。添加,但这不是一个选项,因为 db 开发人员优化了我们的查询,将这个限制从 WHERE 子句带到了连接。

如何在不更改模型定义的情况下快速做到这一点?只更改这一个查询而不更改整个模型?

【问题讨论】:

    标签: sql nhibernate inner-join where-clause


    【解决方案1】:

    感谢您的回答。我们在项目中使用了 2.0 版本的 NHibernate,因此我们没有机会使用 .CreateAlias 的新方法并受到限制。

    我已经使用拦截器解决了一个问题:

    public class SqlInterceptor : EmptyInterceptor, IInterceptor
    {
        SqlString IInterceptor.OnPrepareStatement(SqlString sql)
        {
            //manipulating with the sql
    
            return sql;
        }
    }
    

            var factory = Session.SessionFactory;
            var session = factory.OpenSession(new SqlInterceptor());
    

    并且不加改变地使用我的查询。

    【讨论】:

      【解决方案2】:

      可以使用 HQL 和 Criteria API。

      这个问题给你答案:Adding conditionals to outer joins with nhibernate

      这样的事情可能会解决您的问题。

      .CreateAlias("PersonInt.QuestionEntity", "IntDef", JoinType.LeftOuterJoin, 
            Restrictions.EqProperty("DISCIPLINE_CODE", "IntDef.DISCIPLINE_CODE"))
      

      【讨论】:

      • 这个答案很棒。问题是我们使用的是 2.0.0.4 版本的 nHibernate,我没有可能使用这种方法,而且项目太大而无法在不测试所有代码的情况下更改版本,我们需要快速解决这个问题。也许你知道我如何在 2.0.0.4 中做到这一点?是否有可能操纵 nHibernate 生成的原始 sql?因为其他唯一的解决方案是使用 sql 重写方法。
      • 也许要让执行计划发挥作用,您可以移动那个额外的连接子句并将其添加到 WHERE 子句中。希望 SQL Server 足够聪明,可以将其从内部计划的位置提升到联接,或者为您提供您正在寻找的优化计划。 .Add(Restrictions.EqProperty("DISCIPLINE_CODE", "IntDef.DISCIPLINE_CODE"))
      • 正如我之前所说,这是我们在 where 子句中使用 .Add(Restrictions.EqProperty("DISCIPLINE_CODE", "IntDef.DISCIPLINE_CODE")) 的性能问题。不知道为什么,但是在 join 中使用此限制比在 where 子句中运行得更快。快两倍。我已经通过编写拦截器和使用原始 sql 操作来解决这个问题。谢谢。
      • 抱歉,我无法提供更多帮助。 =(
      猜你喜欢
      • 1970-01-01
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-15
      相关资源
      最近更新 更多