最近のアプリケーションを開発し、ストアドプロシージャのリストのための参照に呼び出す必要があります。
ストアドプロシージャ:proc_test(P1 OUT数、数はP2、TAB_CUSTOMER P3において)。
次のようにこのタイプのリストは、カスタムオラクルのパラメータテーブルです:
TYP_CUSTOMER OF TABLE AS TYPEのTAB_CUSTOMERをCREATE OR REPLACE。
CREATE OR REPLACE TYPEのTYP_CUSTOMERをオブジェクトとして
(
ID VARCHAR2(20)、
NAME VARCHAR2(20)、
GENDER番号、
AGEのNUMBER、
BIRTHDAYのDATE
);
一つの問題:OracleストアドプロシージャにListオブジェクトを渡す方法
間違ったタイプまたはパラメータの数:最初の私は@ProcedureのJPAを使用するには、結果がエラーとなっています。私はこのプロジェクトによ
これは、エンティティクラスのお客様は、Oracle、および同じタイプのTYP_CUSTOMERのフィールドを定義します。合格
ストアドプロシージャの一覧<顧客>。java.util.Listには、必要な手続きを保存するoracle.sql.ARRAYオブジェクトに変換することはできません。
次のようにその後、彼は、同僚や関連する経験、問題解決の相談しました:
[ストアドプロシージャをするoracle.sql.ARRAY渡す方法の問題点を解決するために以下のコードは】
輸入はjava.util.List;
インポートのjava.sql.Connection;
インポートするoracle.sql.ARRAY;
輸入oracle.sql.ArrayDescriptor;
インポートのoracle.sql.STRUCT;
輸入oracle.sql.StructDescriptor;
輸入oracle.sql.DATE;
/ *
以下の方法は、Oracleカスタムとoracle.sql.ARRAYオブジェクトを返す
テーブルマッピングオブジェクト。
@param oracleTypeオラクルのカスタムクラスの
テーブル@param oracleTableオラクルのカスタムクラス
のローカルパッケージリストデータ@list
@return・アレイは、Oracleでカスタマイズすることができoracle.sql.ARRAYオブジェクト
のオブジェクト表をマッピング。
* /
プライベートARRAYは、getOracleArray(CON接続、OracleType文字列、文字列oracleTable、リスト<顧客>リスト)
例外{スロー
配列array = NULLを、
識別するArrayDescriptor DESC =は、ArrayDescriptor.createDescriptor(oracleTable、CON);
STRUCT [] =新しい新しい構造体STRUCT [一覧.size()]。
(もし!リスト= NULL &&はlist.size()> 0){
にStructDescriptor structdesc =新にStructDescriptor(oracleType、CON);
{(; iがLEN <I ++は、I = 0、LEN =はlist.size()INT)のための
オブジェクト[]結果= {
list.get(I).getId()、
list.get(I).getName()、
list.get(I).getGender()、
list.get(I).getAge()、
新しいDATE}(新しいjava.sql.Date(list.get(I).getBirthday()getTime()));
構造体[I] =新しいSTRUCT(structdesc、CON、結果)。
}
アレイ=新しい配列(DESC、CON、構造体)。
}他{
配列=新しいアレイ(DESC、CON、構造体)。
}
の配列を返します。
}
輸入java.util.Date;
クラス顧客{
int型のID。
文字列の名前。
文字列の性別;
int型の年齢;
日付の誕生日。
/ *省略ゲッター/セッター* /
}
第二の問題:接続の最大数は、専用接続プールの要求を開始することができます
次のように問題のコードは次のとおりです。
@Autowired
private HikariDataSource hikariDataSource;
保存します。public void(一覧<顧客>顧客、int型のP2){
接続CONN = NULL;
試す{
CONN =のgetConnection();
PreparedStatementのてpstmt = conn.prepareStatement( "???PKG_TEST.PROC_TEST(、)を呼び出します");
ARRAY P3 =は、getOracleArray(CONN、TYP_CUSTOMER、TAB_CUSTOMER、顧客);
int型P1 = 0;
pstmt.setInt(1、P1)。
pstmt.setInt(2、P2)。
pstmt.setArray(3、P3)。
pstmt.execute();
pstmt.close();
}キャッチ(のSQLException E){
新しいPersistException(e)を投げます。
}キャッチ(例外e){
新しいPersistException(e)を投げます。
}最後に{
場合(connの= nullを!)
{しようと
はconn.closeを();
}キャッチ(例外e){
新しいPersistException(e)を投げます。
}
}
}
プライベート接続のgetConnection(){
接続CONN = NULL;
試す{
CONN = hikariDataSource.getConnection()。
DatabaseMetaDataのmetaData = conn.getMetaData()。
CONN = metaData.getConnection()。
}キャッチ(のSQLException E){
新しいPersistException(e)を投げます。
}
CONN返します。
}
クラスPersistExceptionはのRuntimeExceptionを拡張{/ *省略* /}
ひかりの接続が直接キャストされていないのので、私は、HikariDataSourceにここにあります
Oracleの接続は、その上記の変換をしました。
データベースへの訪問が終了した後に、データベース接続が解除されていないことが表示されます。
テーブルのクエリは、同じ問題を抱えていることができます]
次のような問題を解決するためのコード:
輸入javax.persistence.EntityManager。
輸入javax.persistence.PersistenceContext;
輸入org.hibernate.engine.spi.SessionImplementor。
@PersistenceContext
民間のEntityManagerはEntityManager。
(SaleRetrainingReportレポート)のセーブます。public void {
{しようと
接続CONN = entityManager.unwrap(SessionImplementor.class).connectionを();
CallableStatementのstmt = conn.prepareCall( "PKG_TEST.PROC_TEST(、)を呼び出す???の");
ARRAY P3 =は、getOracleArray(toOracleConnection(CONN)、TYP_CUSTOMER、TAB_CUSTOMER、顧客)。
int型P1 = 0;
stmt.setInt(1、P1)。
stmt.setInt(2、P2)。
stmt.setArray(3、P3)。
でstmt.execute();
stmt.close();
}キャッチ(のSQLException E){
新しいPersistException(e)を投げます。
}キャッチ(例外e){
新しいPersistException(e)を投げます。
}
}
プライベート接続toOracleConnection(接続接続){
接続CONN = NULL;
試す{
DatabaseMetaDataののmetaData = connection.getMetaData()。
CONN = metaData.getConnection()。
}キャッチ(のSQLException E){
新しいPersistException(e)を投げます。
}
CONN返します。
}
---------------------