web-dev-qa-db-ja.com

HibernateとJPAでストアドプロシージャを呼び出すにはどうすればよいですか?

HibernateまたはJPAを使用してストアドプロシージャを呼び出すにはどうすればよいですか?

18
kandarp

次のことができます

 Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
PreparedStatement st = session.connection().prepareStatement("{call procedureName(?, ?)}");
                st.setString(1, formatter.format(parameter1));
                st.setString(2, formatter.format(parameter2));
                st.execute();
tx.commit();

必要に応じて例外処理を追加してください。

1

基本的な戻り値を返すだけの次のストアドプロシージャについて考えてみます。

CREATE OR REPLACE PROCEDURE count_comments (  
   postId IN NUMBER,  
   commentCount OUT NUMBER )  
AS 
BEGIN 
    SELECT COUNT(*) INTO commentCount  
    FROM post_comment  
    WHERE post_id = postId; 
END;

これは標準のJPAで呼び出すことができます。

StoredProcedureQuery query = entityManager
    .createStoredProcedureQuery("count_comments")
    .registerStoredProcedureParameter(1, Long.class, 
        ParameterMode.IN)
    .registerStoredProcedureParameter(2, Long.class, 
        ParameterMode.OUT)
    .setParameter(1, 1L);

query.execute();

Long commentCount = (Long) query.getOutputParameterValue(2);

ストアドプロシージャがSYS_REFCURSORを返す場合:

CREATE OR REPLACE PROCEDURE post_comments ( 
   postId IN NUMBER, 
   postComments OUT SYS_REFCURSOR ) 
AS 
BEGIN
    OPEN postComments FOR
    SELECT *
    FROM post_comment 
    WHERE post_id = postId; 
END;

次のように呼び出すことができます。

StoredProcedureQuery query = entityManager
    .createStoredProcedureQuery("post_comments")
    .registerStoredProcedureParameter(1, Long.class, 
         ParameterMode.IN)
    .registerStoredProcedureParameter(2, Class.class, 
         ParameterMode.REF_CURSOR)
    .setParameter(1, 1L);

query.execute();

List<Object[]> postComments = query.getResultList();

Oracleデータベース関数を呼び出す場合:

CREATE OR REPLACE FUNCTION fn_count_comments ( 
    postId IN NUMBER ) 
    RETURN NUMBER 
IS
    commentCount NUMBER; 
BEGIN
    SELECT COUNT(*) INTO commentCount 
    FROM post_comment 
    WHERE post_id = postId; 
    RETURN( commentCount ); 
END;

StoredProcedureQueryはHibernate 5では機能しないため使用できません。したがって、次のように呼び出すことができます。

BigDecimal commentCount = (BigDecimal) entityManager
    .createNativeQuery(
        "SELECT fn_count_comments(:postId) FROM DUAL"
    )
    .setParameter("postId", 1L)
    .getSingleResult();

またはプレーンJDBCを使用:

Session session = entityManager.unwrap( Session.class ); 

Integer commentCount = session.doReturningWork( connection -> {
    try (CallableStatement function = connection.prepareCall(
            "{ ? = call fn_count_comments(?) }" )) {
        function.registerOutParameter( 1, Types.INTEGER );
        function.setInt( 2, 1 );
        function.execute();
        return function.getInt( 1 );
    }
} );

詳細については、次の記事をご覧ください。

15
Vlad Mihalcea

リモートプロシージャを実行するには、次の構文を使用します。

マッピング

<sql-query name="RP">   
    {call some_rp(:param1, :param2)}
</sql-query>

Javaコード

session.getNamedQuery("RP").setInteger("param1", 1).setInteger("param2", 2).executeUpdate();
2
Mikhail.Mamaev
One way to call the stored procedure from hibernate 

Declare your store procedure inside the @NamedNativeQueries annotation

//Stock.Java

@NamedNativeQueries({
    @NamedNativeQuery(
    name = "callStockStoreProcedure",
    query = "CALL GetStocks(:stockCode)",
    resultClass = Stock.class
    )
})
@Entity
@Table(name = "stock")
public class Stock implements Java.io.Serializable {

Call it with getNamedQuery().

Query query = session.getNamedQuery("callStockStoreProcedure")
    .setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i<result.size(); i++){
    Stock stock = (Stock)result.get(i);
    System.out.println(stock.getStockCode());
}

This works
1
Sandeep Jain

Hibernateの公式ドキュメントサイトにアクセスする必要があります。とにかく リンクはこちら ストアドプロシージャセクションに直接移動します

0

1つの方法として、getNamedQuery()を使用できます。

Query query = session.getNamedQuery("callStockStoreProcedure")
    .setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i<result.size(); i++){
    Stock stock = (Stock)result.get(i);
    System.out.println(stock.getStockCode());
}

アノテーションをマッピングまたは使用する必要があります

他にあります: ソース

0
demian

これは、INパラメータのみを指定してストアドプロシージャを呼び出すための完全なソリューションです---

1)テーブルまたはテーブルセットに作用するストアドプロシージャを作成します。

CREATE OR REPLACE procedure insertHouseHello (
house_date in timestamp,
house_name in varchar2,
house_number in number,
house_value in float) 
is
begin
 insert into House("HOUSE_DATE","HOUSE_NAME","HOUSE_NUMBER","HOUSE_VALUE")
 values ( house_date, house_name,house_number,house_value);
 commit;
 end;

2)SQLプロンプトからストアドプロシージャを実行して、入力を確認します。 Java/Hibernateからプロシージャを呼び出すと、同様の結果が表示されます。

exec insertHouseHello(sysdate,'one',123,104); 

3)Javaコード:

log.info("Now trying to call the Stored Procedure*****************");
Query exQuery = session.createSQLQuery("CALL " +
        "insertHouseHello(:timestmp,:hname,:hno,:hvalue)");
exQuery.setParameter("timestmp", 
        new Java.sql.Timestamp(Calendar.getInstance().getTime().getTime()));
exQuery.setParameter("hname", 34);
exQuery.setParameter("hno", 212);
exQuery.setParameter("hvalue", 12);
int exRows = exQuery.executeUpdate();
log.info("Executed Rows from Stored Procedure****************"+exRows);

4)テーブルの結果を確認します。結果はそれに応じて更新されます。

0
kanaparthikiran

Hibernateは、ストアドプロシージャと関数を介したクエリのサポートを提供します。たとえば、次のストアドプロシージャがあるとします。

_CREATE OR REPLACE FUNCTION selectAllEmployments
RETURN SYS_REFCURSOR
AS
    st_cursor SYS_REFCURSOR;
BEGIN
    OPEN st_cursor FOR
 SELECT EMPLOYEE, EMPLOYER,
 STARTDATE, ENDDATE,
 REGIONCODE, EID, VALUE, CURRENCY
 FROM EMPLOYMENT;
      RETURN  st_cursor;
 END;
_

すべての従業員のリストを返します。ストアドプロシージャ/関数は、Hibernateで動作するための最初の出力パラメーターとして結果セットを返す必要があります。

上記のクエリをHibernateで使用するには、名前付きクエリを介してマップする必要があります。

_<sql-query name="selectAllEmployees_SP" callable="true">
    <return alias="emp" class="Employment">
        <return-property name="employee" column="EMPLOYEE"/>
        <return-property name="employer" column="EMPLOYER"/>
        <return-property name="startDate" column="STARTDATE"/>
        <return-property name="endDate" column="ENDDATE"/>
        <return-property name="regionCode" column="REGIONCODE"/>
        <return-property name="id" column="EID"/>
        <return-property name="salary">
            <return-column name="VALUE"/>
            <return-column name="CURRENCY"/>
        </return-property>
    </return>
    { ? = call selectAllEmployments() }
</sql-query>
_

ストアドプロシージャの使用に関する規則/制限:

  • ストアドプロシージャクエリは、setFirstResult()/ setMaxResults()ではページングできません。
  • 推奨される呼び出し形式は、標準SQL92です:{ ? = call functionName(<parameters>) }または_{ ? = call procedureName(<parameters>}_。ネイティブの呼び出し構文はサポートされていません。

_For Oracle the following rules apply:_

  • 関数は結果セットを返す必要があります。
  • プロシージャの最初のパラメータは、結果セットを返すOUTである必要があります。これは、Oracle 9または10でSYS_REFCURSORタイプを使用して行われます。Oracleでは、REF CURSORタイプを定義する必要があります。詳細については、Oracleの資料を参照してください。

_For Sybase or MS SQL server the following rules apply:_

  • プロシージャは結果セットを返す必要があります。これらのサーバーは複数の結果セットと更新カウントを返す可能性があるため、Hibernateは結果を反復し、結果セットである最初の結果を戻り値として受け取ります。それ以外はすべて破棄されます。
  • プロシージャでSET NOCOUNT ONを有効にできる場合、おそらくより効率的ですが、これは要件ではありません。

出典参照:Hibernateの公式ドキュメントから

0
Lucky