sql >> データベース >  >> RDS >> Oracle

nhibernate、sysrefcursorを返すOracleの関数を呼び出す

    nHibernateを使用してORACLE関数/プロシージャを呼び出す場合、いくつかの制限があります。
    リファレンスドキュメント(17.2.2.1)に記載されているとおり:

    Oracleの場合、次のルールが適用されます

    関数は結果セットを返す必要があります。 aprocedureの最初のパラメーターは、結果セットを返すOUTでなければなりません。これは、Oracle 9または10でSYS_REFCURSORタイプを使用して実行されます。Oracleでは、REFCURSORタイプを定義する必要があります。Oracleの資料を参照してください。

    私は同じ問題を抱えているので、それで少し遊んでみました。

    パッケージの手順は次のとおりです:

    HEAD:

    create or replace
    PACKAGE           "MYPACKAGE" AS
    
        TYPE ReferenceCursor IS REF CURSOR;
    
        PROCEDURE  usp_GetDual 
        (
        pCursor OUT ReferenceCursor,
        a IN CHAR,
        b IN CHAR
        );
    
    END MYPACKAGE;
    

    本体:

    PROCEDURE usp_GetDual
        (
              pCursor OUT ReferenceCursor,
              a IN CHAR,
              b IN CHAR
        )
    
      IS
    
        err_code NUMBER;
        err_msg VARCHAR2(200);
    
      BEGIN
    
      OPEN pCursor FOR
        SELECT * FROM dual;
    
       EXCEPTION
        WHEN OTHERS THEN 
            err_code := SQLCODE;
            err_msg := substr(SQLERRM, 1, 200);
    
    END usp_GetDual;
    

    これは私のマッピングファイルです:

    <?xml version="1.0" encoding="utf-8"?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly">
        <sql-query name="GetDaul">
            { call MYPACKAGE.usp_GetDual ( :a, :b ) }
        </sql-query>
    </hibernate-mapping>
    

    これは私がテストに使用したコードです:

    var value = Session.GetNamedQuery("GetDaul")
        .SetParameter<string>("a", "AAA")
        .SetParameter<string>("b", "BBB")
        .UniqueResult();
    

    ご覧のとおり、REF CURSORは、プロシージャの最初のパラメータである必要があります(pCursor OUT ReferenceCursor )そして、マッピングや呼び出しでそれを参照する必要はありません。

    エンティティを返したい場合は、もう少し複雑になります。

    マッピングファイルでは、リターンタイプ(クラス)を指定する必要があります:

    <?xml version="1.0" encoding="utf-8"?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly">
        <sql-query name="GetOrders">
             <return class="MyAssembly.Domain.MyOrder, MyAssembly" />
             { call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) }
        </sql-query>
    </hibernate-mapping>
    

    エンティティを定義する必要があります:

    public class MyOrder
    {
        public virtual string Number { get; set; }
        public virtual int Ver { get; private set; }
        public virtual string Company { get; set; }
        public virtual string Customer { get; set; }
    
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            Order order = obj as Order;
            if (order == null)
                return false;
            if (this.Number.Trim() == order.Number.Trim() &&
                this.Ver == order.Ver &&
                this.Company.Trim() == order.Company.Trim()
                )
                return true;
            else
                return false;
        }
    
        public override int GetHashCode()
        {
            int hash = 0;
            hash = hash +
                (null == this.Number ? 0 : this.Number.GetHashCode())
                +
                (this.Ver.GetHashCode())
                +
                (null == this.Company ? 0 : this.Company.GetHashCode());
    
            return (hash);
        }
    }
    

    これはエンティティのマッピングファイルです:

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly" namespace="MyAssembly.Domain">
      <class name="MyOrder" table="OCSAORH" mutable="false">
        <composite-id>
          <key-property name="Number" column="OCHORDN" type="String" length="10"></key-property>
          <key-property name="Ver" column="OCHAMND" type="Int32"></key-property>
          <key-property name="Company" column="OCHCOSC" type="String" length="5"></key-property>
        </composite-id>
        <property name="Customer" column="OCHCLII" type="String"></property>
      </class>
    </hibernate-mapping>
    

    これは私のORACLEパッケージです:

    PROCEDURE usp_GetOrders 
              (
              pCursor OUT ReferenceCursor,
              pCompanyCode IN CHAR,
              pOrderNumer IN CHAR
          )
    
      IS
    
        err_code NUMBER;
        err_msg VARCHAR2(200);
    
      BEGIN
    
      OPEN pCursor FOR
           SELECT 
                OCSAORH.*
          FROM OCSAORH 
                WHERE OCSAORH.OCHAMND = 0
                    AND OCSAORH.OCHCOSC = pCompanyCode
                    AND OCSAORH.OCHORDN = pOrderNumer;              
        EXCEPTION
                WHEN OTHERS THEN 
              err_code := SQLCODE;
              err_msg := substr(SQLERRM, 1, 200);
    
    END usp_GetOrders;
    

    そして今、あなたはパラメータを使ってあなたの注文を簡単に得ることができます:

    var listOfOrders = Session.GetNamedQuery("GetOrder")
        .SetParameter<string>("pCompanyCode", "ABC")
            .SetParameter<string>("pOrderNumer", "XYZ")
            .List<Domain.MyOrder>();
    

    この記事は、物事がどのように行われなければならないかを理解するのに役立ちました。



    1. データベースとデータファイルを移行する方法

    2. psqlクエリ結果でテーブルの境界線スタイルを変更する方法

    3. SSRSレポート定義はサーバーよりも新しい

    4. ダウンタイムなしでDjangoでインデックスを作成する方法