【问题标题】:Implementing a complex query in NHibernate?在 NHibernate 中实现一个复杂的查询?
【发布时间】:2010-11-17 02:00:36
【问题描述】:

我使用 NHibernate 已经有一段时间了,但主要是使用基于约定的自动持久性模型生成,然后对对象执行基本的 CRUD 操作。

我现在需要对遗留系统执行一个相当讨厌的查询以及一堆参数(大部分 where 子句需要参数化)。我不清楚是否应该定义单个对象,然后尝试实现复杂的查询,或者只是使用本机 SQL 来定义查询。我也不清楚在 hbm.xml 文件中定义查询的正确语法。接下来是本机 SQL 查询。感谢任何可以帮助我解决这个问题的人。

WITH CTE AS ( SELECT
    substr(KEY1||KEY2||KEY3||'-'||digits(KEY4)||'-'||digits(KEY5),1,17) KEY_ID,
    SUM(CASE WHEN BATCH between 200801001 and 200812999 THEN TRANSACTION_AMOUNT ELSE 0 END) AS _2008AMOUNT,
    SUM(CASE WHEN BATCH between 200901001 and 200912999 THEN TRANSACTION_AMOUNT ELSE 0 END) AS _2009AMOUNT,
    SUM(CASE WHEN BATCH between 201001001 and 201012999 THEN TRANSACTION_AMOUNT ELSE 0 END) AS _2010AMOUNT

    FROM _SCHEMA.TRANSACTIONS

    WHERE OWNER='02'
    AND TRANSACTION_TYPE in ('A','B')
    AND BATCH between 200801000 AND 201012999

    GROUP BY KEY1, KEY2, KEY3, KEY4, KEY5

    HAVING SUM(CASE WHEN BATCH between 200801001 and 200812999 THEN TRANSACTION_AMOUNT ELSE 0 END)  0
    OR SUM(CASE WHEN BATCH between 200901001 and 200912999 THEN TRANSACTION_AMOUNT ELSE 0 END)  0
    OR SUM(CASE WHEN BATCH between 201001001 and 201012999 THEN TRANSACTION_AMOUNT ELSE 0 END)  0
    )


    SELECT
    B.OWNER
    ,CTE1.MAX_ITEM_AMOUNT
    ,CTE1.SUM_ITEM_AMOUNT
    ,B.PRIMARY_SECONDARY_IDENTITY
    ,B.PRIMARY_ID
    ,B.PRIMARY_NAME
    ,B.KEY_ID
    ,B.KEY_AMOUNT
    ,CASE(B.KEYCLASS) WHEN 'C' THEN 'CLASS1' WHEN 'S' THEN 'CLASS2' WHEN 'M' THEN 'CLASS3' WHEN 'F' THEN 'CLASS4' END AS KEYCLASS
    ,NA.PRIMARY_CT AS PRIMARY_CITY
    ,NA.PRIMARY_ST AS PRIMARY_STATE
    ,B.KEY_EFFECTIVE_DATE
    ,B.KEY_ENTRY_DATE
    ,CTE._2008AMOUNT
    ,CTE._2009AMOUNT
    ,CTE._2010AMOUNT
    ,B.EMPLOYEE_NAME

    FROM CTE

    JOIN _SCHEMA.TABLE2 B ON CTE.KEY_ID = B.KEY_ID

    JOIN (
    SELECT
    PRIMARY_SECONDARY_IDENTITY
    , MAX(ITEM_AMOUNT) AS MAX_ITEM_AMOUNT
    , SUM(ITEM_AMOUNT) AS SUM_TTEM_AMOUNT
    FROM CTE
    JOIN _SCHEMA.TABLE2 B ON CTE.KEY_ID = B.KEY_ID
    GROUP BY PRIMARY_SECONDARY_IDENTITY
    ) CTE1 ON CTE1.PRIMARY_SECONDARY_IDENTITY = B.PRIMARY_SECONDARY_IDENTITY

    JOIN _SCHEMA.TABLE3 NA ON B.PRIMARY_ID = NA.KEY1 || DIGITS(NA.KEY2)

    ORDER BY MAX_ITEM_AMOUNT DESC, PRIMARY_SECONDARY_IDENTITY
    

【问题讨论】:

  • 我的回答是否回答了问题?如果是这样,请接受它,以便为我们 SO 的同事寻找这样的解决方案提供一个好的解决方案。

标签: sql nhibernate nhibernate-mapping


【解决方案1】:

这种交易无论如何都要通过命名查询来处理。

NHibernate 允许一些简单的 CRUD 操作无法完成的预配置命名查询。我建议您注意在 NHibernate 文档中使用这些。

15.2. Named SQL queries

另一方面,您可能对原生 SQL 查询感兴趣。

9.3.5. Queries in native SQL

【讨论】:

  • 同意。这是一个例子:ayende.com/Blog/archive/2009/04/17/…
  • 谢谢,我对文档和大多数示例的问题是它们相当贫乏。很难看出 Common Table Expressions、Group By 和 Sub Queries 的影响。该文档似乎暗示需要以特定方式表达连接,即使在本机 SQL 中也是如此,但没有什么比处理上述查询中涉及的细节更接近了。
  • 也许你应该考虑用这段代码编写一个存储过程,并让这个存储过程成为一个命名查询。
  • SP 不会破坏遗留系统中的任何内容,尽管我最好了解您的情况。我看到的另一个选择是将这个复杂的代码拆分为工作单元,使每个单元成为一个命名查询(或本机 SQL),并从代码中完成数据处理,将第一个查询的所需结果值作为参数传递给第二个根据需要等等。
  • 同意;有时 linq 和标准(甚至 hql)达不到要求,使用本机 sql 在需要的地方完成工作并没有错。只要确保尽可能集中使用它(使用命名查询是一个很好的开始)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2018-12-03
相关资源
最近更新 更多