ストアドプロシージャを呼び出してデータを取得する簡単なWebアプリケーションを作成しています。クライアントのデータベースと対話する非常にシンプルなアプリケーション。従業員IDと会社IDを渡すと、ストアドプロシージャが従業員の詳細を返します。
Webアプリケーションはデータを更新/削除できず、SQL Serverを使用しています。
WebアプリケーションをJboss ASにデプロイしています。 JPAを使用してストアドプロシージャまたはCallableStatement
にアクセスする必要があります。この場合にJPAを使用する利点。
また、このストアドプロシージャを呼び出すsqlステートメントはどうなりますか。私は以前にストアドプロシージャを使用したことがなく、これに苦労しています。 Googleはあまり役に立ちませんでした。
ストアドプロシージャは次のとおりです。
CREATE procedure getEmployeeDetails (@employeeId int, @companyId int)
as
begin
select firstName,
lastName,
gender,
address
from employee et
where et.employeeId = @employeeId
and et.companyId = @companyId
end
更新:
JPAを使用してストアドプロシージャの呼び出しに問題がある他のユーザー向け。
Query query = em.createNativeQuery("{call getEmployeeDetails(?,?)}",
EmployeeDetails.class)
.setParameter(1, employeeId)
.setParameter(2, companyId);
List<EmployeeDetails> result = query.getResultList();
私が気づいたこと:
{call sp_name(?,?)}
の代わりにSQLステートメントcall sp_name(?,?)
を修正getSingleResult
は機能しませんresultSetMapping
の名前または結果クラスの詳細を渡すJPA 2.1はストアドプロシージャをサポートするようになりました。Java doc here を読んでください。
例:
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("sales_tax");
// set parameters
storedProcedure.registerStoredProcedureParameter("subtotal", Double.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("tax", Double.class, ParameterMode.OUT);
storedProcedure.setParameter("subtotal", 1f);
// execute SP
storedProcedure.execute();
// get result
Double tax = (Double)storedProcedure.getOutputParameterValue("tax");
詳細な例を参照してください here 。
WebアプリケーションをJboss ASにデプロイしています。 JPAを使用してストアドプロシージャまたはCallableStatementにアクセスする必要があります。この場合にJPAを使用する利点。
JPAでは実際にはサポートされていませんが、 実行可能 です。それでも私はこのようには行きません:
したがって、 JDBCデータアクセスのスプリングサポート 、または MyBatis のようなデータマッパーを使用するか、アプリケーションの単純さを考慮して、生のJDBCとCallableStatement
。実際、おそらくJDBCが私の選択でしょう。基本的なキックオフの例を次に示します。
CallableStatement cstmt = con.prepareCall("{call getEmployeeDetails(?, ?)}");
cstmt.setInt("employeeId", 123);
cstmt.setInt("companyId", 456);
ResultSet rs = cstmt.executeQuery();
ストアドプロシージャにパラメーターを渡す必要があります。
次のように動作するはずです。
List result = em
.createNativeQuery("call getEmployeeDetails(:employeeId,:companyId)")
.setParameter("emplyoyeeId", 123L)
.setParameter("companyId", 456L)
.getResultList();
更新:
または多分それはすべきではありません。
本では EJB3 in Action 、383ページで JPAはストアドプロシージャをサポートしていません (ページはプレビューにすぎず、全文は表示されませんが、本全体が this one を含むいくつかの場所でダウンロードとして入手できますが、これが合法かどうかはわかりません)。
とにかく、テキストはこれです:
SQLの大ファンであれば、データベースストアドプロシージャの能力を活用することもできます。残念ながら、JPAはストアドプロシージャをサポートしていないため、永続性プロバイダーの独自機能に依存する必要があります。ただし、ネイティブSQLクエリで単純なストアド関数(出力パラメーターなし)を使用できます。
この回答は、ストアドプロシージャからレコードセットを返すことについて詳しく説明していますが、それを理解するには時間がかかり、このスレッドが私を助けてくれたので、ここに投稿しています。
私のアプリケーションはEclipselink-2.3.1を使用していましたが、JPA 2.1はストアドプロシージャのサポートがはるかに優れているため、Eclipselink-2.5.0へのアップグレードを強制します。
この方法では、「org.Eclipse.persistence」からEclipseLinkクラスをインポートする必要があるため、Eclipselink実装に固有です。
「 http://www.yenlo.nl/en/calling-Oracle-stored-procedures-from-eclipselink-with-multiple-out-parameters 」で見つけました。
StoredProcedureCall storedProcedureCall = new StoredProcedureCall();
storedProcedureCall.setProcedureName("mypackage.myprocedure");
storedProcedureCall.addNamedArgument("i_input_1"); // Add input argument name.
storedProcedureCall.addNamedOutputArgument("o_output_1"); // Add output parameter name.
DataReadQuery query = new DataReadQuery();
query.setCall(storedProcedureCall);
query.addArgument("i_input_1"); // Add input argument names (again);
List<Object> argumentValues = new ArrayList<Object>();
argumentValues.add("valueOf_i_input_1"); // Add input argument values.
JpaEntityManager jpaEntityManager = (JpaEntityManager) getEntityManager();
Session session = jpaEntityManager.getActiveSession();
List<?> results = (List<?>) session.executeQuery(query, argumentValues);
DatabaseRecord record = (DatabaseRecord) results.get(0);
String result = String.valueOf(record.get("o_output_1")); // Get output parameter
このメソッドは実装に依存しません(Eclipslinkのインポートは不要です)。
StoredProcedureQuery query = getEntityManager().createStoredProcedureQuery("mypackage.myprocedure");
query.registerStoredProcedureParameter("i_input_1", String.class, ParameterMode.IN);
query.registerStoredProcedureParameter("o_output_1", String.class, ParameterMode.OUT);
query.setParameter("i_input_1", "valueOf_i_input_1");
boolean queryResult = query.execute();
String result = String.valueOf(query.getOutputParameterValue("o_output_1"));
EclipseLinkを使用している場合は、@ NamedStoredProcedureQueryまたはStoreProcedureCallを使用して、出力パラメーターやアウトカーソルを含むストアドプロシージャを実行できます。ストアドファンクションおよびPLSQLデータ型のサポートも利用可能です。
http://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#Stored_Procedures を参照してください
私にとっては、Oracle 11gおよびGlassfish 2.1(Toplink)で動作するのは次のものだけです。
Query query = entityManager.createNativeQuery("BEGIN PROCEDURE_NAME(); END;");
query.executeUpdate();
中括弧のあるバリアントは、ORA-00900になりました。
このようなIN/OUTパラメータを使用する単純なストアドプロシージャの場合
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
OUTパラメーターを使用するストアドプロシージャの場合:
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();
次のようなSQL関数の場合:
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;
次のように呼び出すことができます。
BigDecimal commentCount = (BigDecimal) entityManager
.createNativeQuery(
"SELECT fn_count_comments(:postId) FROM DUAL"
)
.setParameter("postId", 1L)
.getSingleResult();
少なくともHibernate 4.xおよび5.xを使用する場合、JPA StoredProcedureQuery
はSQL FUNCTIONSでは機能しないためです。
JPAとHibernateを使用するときにストアドプロシージャと関数を呼び出す方法の詳細については、次の記事をご覧ください。
次は私のために働く:
Query query = em.createNativeQuery("BEGIN VALIDACIONES_QPAI.RECALC_COMP_Assembly('X','X','X',0); END;");
query.executeUpdate();
これは私のために働いた。
@Entity
@Table(name="acct")
@NamedNativeQueries({
@NamedNativeQuery(callable=true, name="Account.findOne", query="call sp_get_acct(?), resultClass=Account.class)})
public class Account{
// Code
}
注:将来、findOneのデフォルトバージョンを使用することにした場合は、NamedNativeQueriesアノテーションにコメントするだけで、JPAはデフォルトに切り替わります
Sql Srverと同じではないかもしれませんが、OracleとEclipslinkを使用している人々にとってはそれが私のために働いています
例:1つのINパラメーター(タイプCHAR)と2つのOUTパラメーター(NUMBER&VARCHAR)を持つプロシージャー
persistence.xmlでpersistence-unitを宣言します:
<persistence-unit name="presistanceNameOfProc" transaction-type="RESOURCE_LOCAL">
<provider>org.Eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/DataSourceName</jta-data-source>
<mapping-file>META-INF/eclipselink-orm.xml</mapping-file>
<properties>
<property name="eclipselink.logging.level" value="FINEST"/>
<property name="eclipselink.logging.logger" value="DefaultLogger"/>
<property name="eclipselink.weaving" value="static"/>
<property name="eclipselink.ddl.table-creation-suffix" value="JPA_STORED_PROC" />
</properties>
</persistence-unit>
eclipselink-orm.xmlでprocの構造を宣言します
<?xml version="1.0" encoding="UTF-8"?><entity-mappings version="2.0"
xmlns="http://Java.Sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://Java.Sun.com/xml/ns/persistence/orm orm_2_0.xsd">
<named-stored-procedure-query name="PERSIST_PROC_NAME" procedure-name="name_of_proc" returns-result-set="false">
<parameter direction="IN" name="in_param_char" query-parameter="in_param_char" type="Character"/>
<parameter direction="OUT" name="out_param_int" query-parameter="out_param_int" type="Integer"/>
<parameter direction="OUT" name="out_param_varchar" query-parameter="out_param_varchar" type="String"/>
</named-stored-procedure-query>
コードでは、次のようにprocを呼び出す必要があります。
try {
final Query query = this.entityManager
.createNamedQuery("PERSIST_PROC_NAME");
query.setParameter("in_param_char", 'V');
resultQuery = (Object[]) query.getSingleResult();
} catch (final Exception ex) {
LOGGER.log(ex);
throw new TechnicalException(ex);
}
2つの出力パラメータを取得するには:
Integer myInt = (Integer) resultQuery[0];
String myStr = (String) resultQuery[1];
この回答は、エンティティマネージャーがいる場合に役立ちます。
次の番号を作成するストアドプロシージャがあり、サーバー側にはseamフレームワークがあります。
クライアント側
Object on = entityManager.createNativeQuery("EXEC getNextNmber").executeUpdate();
log.info("New order id: " + on.toString());
データベース側(SQLサーバー)getNextNmber
という名前のストアドプロシージャがあります
JPA 2.0はRETURN値をサポートせず、呼び出しのみをサポートします。
私の解決策は。 PROCEDUREを呼び出すFUNCTIONを作成します。
したがって、Javaコード内で、Oracle FUNCTIONを呼び出すネイティブクエリを実行します。
JPA 2.1以降、JPAは、動的なStoredProcedureQueryおよび宣言的な@NamedStoredProcedureQueryを使用してストアドプロシージャを呼び出すことをサポートしています。
このコードを試してください:
return em.createNativeQuery("{call getEmployeeDetails(?,?)}",
EmployeeDetails.class)
.setParameter(1, employeeId)
.setParameter(2, companyId).getResultList();
リポジトリで@Query(value = "{call PROC_TEST()}", nativeQuery = true)
を使用できます。これは私のために働いた。
注意:「{」と「}」を使用しないと、機能しません。
persistence.xml
<persistence-unit name="PU2" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>jndi_ws2</non-jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
コディゴJava
String PERSISTENCE_UNIT_NAME = "PU2";
EntityManagerFactory factory2;
factory2 = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em2 = factory2.createEntityManager();
boolean committed = false;
try {
try {
StoredProcedureQuery storedProcedure = em2.createStoredProcedureQuery("PKCREATURNO.INSERTATURNO");
// set parameters
storedProcedure.registerStoredProcedureParameter("inuPKEMPRESA", BigDecimal.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("inuPKSERVICIO", BigDecimal.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("inuPKAREA", BigDecimal.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("isbCHSIGLA", String.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("INUSINCALIFICACION", BigInteger.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("INUTIMBRAR", BigInteger.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("INUTRANSFERIDO", BigInteger.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("INTESTADO", BigInteger.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("inuContador", BigInteger.class, ParameterMode.OUT);
BigDecimal inuPKEMPRESA = BigDecimal.valueOf(1);
BigDecimal inuPKSERVICIO = BigDecimal.valueOf(5);
BigDecimal inuPKAREA = BigDecimal.valueOf(23);
String isbCHSIGLA = "";
BigInteger INUSINCALIFICACION = BigInteger.ZERO;
BigInteger INUTIMBRAR = BigInteger.ZERO;
BigInteger INUTRANSFERIDO = BigInteger.ZERO;
BigInteger INTESTADO = BigInteger.ZERO;
BigInteger inuContador = BigInteger.ZERO;
storedProcedure.setParameter("inuPKEMPRESA", inuPKEMPRESA);
storedProcedure.setParameter("inuPKSERVICIO", inuPKSERVICIO);
storedProcedure.setParameter("inuPKAREA", inuPKAREA);
storedProcedure.setParameter("isbCHSIGLA", isbCHSIGLA);
storedProcedure.setParameter("INUSINCALIFICACION", INUSINCALIFICACION);
storedProcedure.setParameter("INUTIMBRAR", INUTIMBRAR);
storedProcedure.setParameter("INUTRANSFERIDO", INUTRANSFERIDO);
storedProcedure.setParameter("INTESTADO", INTESTADO);
storedProcedure.setParameter("inuContador", inuContador);
// execute SP
storedProcedure.execute();
// get result
try {
long _inuContador = (long) storedProcedure.getOutputParameterValue("inuContador");
varCon = _inuContador + "";
} catch (Exception e) {
}
} finally {
}
} finally {
em2.close();
}
ストアドプロシージャを呼び出すには、Java.sqlパッケージのCallable Statementを使用できます。