13

sys-refcursor を返す Oracle 関数があり、Hibernate を使用してこの関数を呼び出すと、次の例外が発生します。

Hibernate: { ? = call my_function(?) }
 org.hibernate.exception.GenericJDBCException: could not execute query
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1360)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1288)
    at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:313)

どうすればこれを解決できますか?

オラクル関数

create or replace 
FUNCTION my_function(p_val IN varchar2)
    RETURN SYS_REFCURSOR
  AS
    my_cursor SYS_REFCURSOR;
  BEGIN
    OPEN my_cursor FOR SELECT emp_name FROM employees
    WHERE lower(emp_name) like lower(p_val||'%');
    RETURN my_cursor;    
  END;

私のエンティティクラス

@Entity
@javax.persistence.NamedNativeQuery(name = "getFunc", query = 
"{ ? = call my_function(:empName) }", 
 resultClass = Employee.class, hints = 
 { @javax.persistence.QueryHint(name = "org.hibernate.callable", value = "true") })
 @Table(name = "EMPLOYEES")

そしてDAOで

    @Override
        public void findEmployees(QueryData data,
                String empName) {

        List query = (List) entityManager.createNamedQuery("getFunc")
                         .setParameter("empName", empName)
                         .getSingleResult();
                data.setResult(query);
}
4

6 に答える 6

20

Oracle 関数またはストアド プロシージャは、次の方法で EntityManager を使用して呼び出すことができます。

Oracle 関数の場合

sys_refcursor を戻り値の型として関数を作成する

CREATE OR REPLACE FUNCTION my_function
(p_val IN varchar2)
    RETURN SYS_REFCURSOR
  AS
    my_cursor SYS_REFCURSOR;
  BEGIN
    OPEN my_cursor FOR SELECT emp_name FROM employees
    WHERE lower(emp_name) like lower(p_val||'%');
    RETURN my_cursor;    
  END;

Entity クラスで、関数を次のように定義します。

@javax.persistence.NamedNativeQuery(name = "getFunc", query = "{? =  call
my_function(:empName) }", resultClass = Employee.class, hints = {
@javax.persistence.QueryHint(name = "org.hibernate.callable", value = "true") })

Oracle ストアド プロシージャの場合

sys_refcursor最初の OUT パラメータとしてプロシージャを作成する

CREATE OR REPLACE PROCEDURE myProcedure(p_cursor out sys_refcursor,
     p_val  in varchar2
)
 AS
BEGIN
     OPEN o_cursor FOR
          SELECT     emp_name 
             FROM     employees 
            WHERE     LOWER (emp_name) LIKE lower(p_val||'%');

エンティティクラスでは、プロシージャを次のように定義します

@javax.persistence.NamedNativeQuery(name = "getProc", query = "{ call
my_procedure(?,:empName) }", resultClass = Employee.class, hints = {
@javax.persistence.QueryHint(name = "org.hibernate.callable", value = "true") })

そして最後にDAOクラスで関数またはプロシージャを次のように呼び出します

Query query = entityManager.createNamedQuery("getFunc"); // if procedure then getProc 
query.setParameter("empName","smith"); 
query.getResultList(); 

ありがとう

于 2013-02-06T06:02:07.527 に答える
2

Oracle 関数と Oracle ストアド プロシージャを混同しているようです。

関数は select ステートメントから呼び出すことができます。あなたのようなユーザー定義関数は、min() や max() などの組み込み関数と同じように動作します。ストアド プロシージャのように、外部の「呼び出し」によって呼び出すことはできません。

関数の定義については、http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions231.htm#i1012049を参照してください。

おそらく、関数をストアド プロシージャとして書き直す必要があります。

于 2013-01-15T13:28:21.170 に答える
1

前のソリューションは、eclipselink では機能しないようです。JPAの下でネイティブクエリを使用してこれを実行しました

            List result = em.createNativeQuery("select YOURFUNCTION(?) from dual ")
                      .setParameter(1, ONEPARAMETER)
                      .getResultList();
于 2015-05-08T06:37:12.580 に答える
1

Oracleの Arun Gupta 氏によると、JPA 2.1 の初期ドラフトでは、ストアド プロシージャがサポートされると述べられています。

ストアド プロシージャのサポート: 定義済みデータベース関数とユーザー定義データベース関数の呼び出しのサポートが Java Persistence クエリ言語に追加されました。

EntityManager.createXXXStoredProcedureQueryストアド プロシージャを実行するための StoredProcedureQuery を返すメソッドには、さまざまなバリエーションがあります。好きなだけ、ストアドプロシージャ、そのパラメーター、およびその結果の型を指定して名前を付けるがあります@NamedQuery@NamedStoredProcedureQueryこの注釈は、エンティティまたはマップされたスーパークラスで指定できます。注釈で指定された名前は、 で使用されEntityManager.createNamedStoredProcedureQueryます。IN、OUT、および INOUT パラメータを設定して、プロシージャから返された値を取得するために使用できます。例えば:

@Entity
@NamedStoredProcedureQuery(name="topGiftsStoredProcedure", procedureName="Top10Gifts")
public class Product {
 . . .
}

// In your client

StoredProcedreQuery query = EntityManager.createNamedStoredProcedureQuery("topGiftsStoredProcedure");
query.registerStoredProcedureParameter(1, String.class, ParameterMode.INOUT);
query.setParameter(1, "top10");
query.registerStoredProcedureParameter(2, Integer.class, ParameterMode.IN);
query.setParameter(2, 100);
// there are other setParameter methods for defining the temporal type of a parameter
. . .
query.execute();
String response = query.getOutputParameterValue(1);

仕様がいつ完成するのか、または Hibernate がいつ JPA 2.1 をサポートするのかについては、私にはわかりません。しかし、注意する価値があるかもしれません。

于 2013-01-17T02:53:54.710 に答える