我希望得到您的幫助,我嘗試了幾件事情,但無法解決我的問題。如何使用Eclipselink運行Oracle PROCEDER 2.4返回SYS_REFCURSOR
我使用:的EclipseLink 2.42和甲骨文11
我需要執行返回SYS_REFCURSOR的操作,但是我不能執行使用的EclipseLink(JPA)此過程中,我嘗試了幾種方式,在我看來,API不能識別SYS_REFCURSOR類型。
可能有人請幫助我,我已經沒了主意,使這項工作
這是我的程序:
PROCEDURE RETRIEVE_JOBS(JOB_ID_PARAM IN FAC_JOB_INTEGRATION.FACT_JOB_ENTRY_REC
, JOBS_PARAM OUT SYS_REFCURSOR) IS
vDescErro VARCHAR2(2000);
BEGIN
OPEN JOBS_PARAM FOR
SELECT *
FROM dba_jobs
--WHERE job = NVL(pJOB,job)
ORDER BY job;
EXCEPTION WHEN OTHERS THEN
vDescErro := REPLACE(SQLERRM, '"' ,' ');
vDescerro := REPLACE(vDescErro, CHR(10),'');
END RETRIEVE_JOBS;
,這裏是一些測試,結果:
StoredProcedureCall functionCall = new StoredProcedureCall();
functionCall.setProcedureName("FAC_JOB_INTEGRATION.RETRIEVE_JOBS");
functionCall.addNamedArgument("JOB_ID_PARAM");
functionCall.useNamedCursorOutputAsResultSet("JOBS_PARAM");
DataReadQuery querytestS = new DataReadQuery();
querytestS.addArgument("JOB_ID_PARAM");
querytestS.setCall(functionCall);
// Adding arguments
List<Object> queryArgstestS = new ArrayList<Object>();
queryArgstestS.add(entrada);
querytestS.bindAllParameters();
// Executing query
session = ((JpaEntityManager)getEntityManager().getDelegate()).getActiveSession();
Object result232 = session.executeQuery(querytestS, queryArgstestS);
我的錯誤:
[EL Fine]: 2017-05-05 15:33:03.886--ServerSession(23378162)--Connection(19739591)--BEGIN FAC_JOB_INTEGRATION.RETRIEVE_JOBS(JOB_ID_PARAM=>?, JOBS_PARAM=>?); END;
bind => [TipoEntrada [jobId=200], => JOBS_PARAM]
[EL Fine]: 2017-05-05 15:33:03.886--ServerSession(23378162)--SELECT 1 FROM DUAL
[EL Warning]: 2017-05-05 15:33:04.06--UnitOfWork(19720277)--Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Invalid type Column
Error Code: 17004
Call: BEGIN FAC_JOB_INTEGRATION.RETRIEVE_JOBS(JOB_ID_PARAM=>?, JOBS_PARAM=>?); END;
bind => [TipoEntrada [jobId=200], => JOBS_PARAM]
Query: DataReadQuery()
第二個測試:
PLSQLStoredProcedureCall call2 = new PLSQLStoredProcedureCall();
call2.setProcedureName("FAC_JOB_INTEGRATION.RETRIEVE_JOBS");
call2.addNamedArgument("JOB_ID_PARAM", TipoEntrada.getRecord());
call2.useNamedCursorOutputAsResultSet("JOBS_PARAM");
DataReadQuery querytest = new DataReadQuery();
querytest.addArgument("JOB_ID_PARAM");
querytest.setCall(call2);
// Adding arguments
List<Object> queryArgstest = new ArrayList<Object>();
queryArgstest.add(entrada);
querytest.bindAllParameters();
// Executing query
session = ((JpaEntityManager)
getEntityManager().getDelegate()).getActiveSession();
Object result23 = session.executeQuery(querytest, queryArgstest);
錯誤結果:
Local Exception Stack:
Exception [EclipseLink-6148] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.QueryException
Exception Description: Adding named OUT cursor arguments without DatabaseType classification to PLSQLStoredProcedureCall is not supported.
at org.eclipse.persistence.exceptions.QueryException.addArgumentsNotSupported(QueryException.java:1417)
現在我創建一個OracleCursorDatabaseType:
import static org.eclipse.persistence.internal.helper.DatabaseType.DatabaseTypeHelper.databaseTypeHelper;
import static org.eclipse.persistence.internal.helper.Helper.NL;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.SimpleDatabaseType;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
import oracle.jdbc.OracleTypes;
@SuppressWarnings("rawtypes")
public class OracleCursorDatabaseType implements SimpleDatabaseType {
public boolean isComplexDatabaseType() {
return false;
}
public boolean isJDBCType() {
return false;
}
public int getSqlCode() {
return OracleTypes.CURSOR;
}
public int getConversionCode() {
return getSqlCode();
}
public String getTypeName() {
return "SYS_REFCURSOR";
}
public int computeInIndex(PLSQLargument inArg, int newIndex, ListIterator<PLSQLargument> i) {
inArg.outIndex = newIndex;
return ++newIndex;
}
public int computeOutIndex(PLSQLargument outArg, int newIndex, ListIterator<PLSQLargument> iterator) {
outArg.outIndex = newIndex;
return newIndex;
}
public void buildInDeclare(StringBuilder sb, PLSQLargument inArg) {
System.out.println("buildInDeclare");
}
public void buildOutDeclare(StringBuilder sb, PLSQLargument outArg) {
sb.append(" ");
sb.append(databaseTypeHelper.buildTarget(outArg));
sb.append(" ");
sb.append(getTypeName());
sb.append(";");
sb.append(NL);
}
public void buildBeginBlock(StringBuilder sb, PLSQLargument arg, PLSQLStoredProcedureCall call) {
System.out.println("buildBeginBlock");
}
public void buildOutAssignment(StringBuilder sb, PLSQLargument outArg, PLSQLStoredProcedureCall call) {
String target = databaseTypeHelper.buildTarget(outArg);
sb.append(" :");
sb.append(outArg.outIndex);
sb.append(" := ");
sb.append(target);
sb.append(";");
sb.append(NL);
}
public void translate(PLSQLargument arg, AbstractRecord translationRow, AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields, List<DatabaseField> translationRowFields,
List translationRowValues, StoredProcedureCall call) {
// TODO Auto-generated method stub
System.out.println("translate");
}
public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow, DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) {
databaseTypeHelper.buildOutputRow(outArg, outputRow, newOutputRow, outputRowFields, outputRowValues);
}
public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg, AbstractRecord translationRow, DatabasePlatform platform) {
System.out.println("logParameter");
}
}
第一個測試:
PLSQLStoredProcedureCall call2 = new PLSQLStoredProcedureCall();
call2.setProcedureName("FAC_JOB_INTEGRATION.RETRIEVE_JOBS");
call2.addNamedArgument("JOB_ID_PARAM", TipoEntrada.getRecord());
call2.addNamedOutputArgument("JOBS_PARAM", new OracleCursorDatabaseType());
// Preparing the query
DataReadQuery querytest = new DataReadQuery();
querytest.addArgument("JOB_ID_PARAM");
querytest.setCall(call2);
// Adding arguments
List<Object> queryArgstest = new ArrayList<Object>();
queryArgstest.add(entrada);
querytest.bindAllParameters();
// Executing query
session = ((JpaEntityManager) getEntityManager().getDelegate()).getActiveSession();
Object result23 = session.executeQuery(querytest, queryArgstest);
的程序是運行W¯¯ ithout問題,但不會返回光標值:
日誌執行:
[EL Fine]: 2017-05-05 15:51:55.933--ServerSession(23378162)--Connection(15936168)--
DECLARE
JOB_ID_PARAMTARGET FAC_JOB_INTEGRATION.FACT_JOB_ENTRY_REC;
JOB_ID_PARAMCOMPAT FACT_JOB_ENTRY := :1;
JOBS_PARAMTARGET SYS_REFCURSOR;
FUNCTION EL_SQL2PL_1(aSqlItem FACT_JOB_ENTRY)
RETURN FAC_JOB_INTEGRATION.FACT_JOB_ENTRY_REC IS
aPlsqlItem FAC_JOB_INTEGRATION.FACT_JOB_ENTRY_REC;
BEGIN
aPlsqlItem.JOB := aSqlItem.JOB;
RETURN aPlsqlItem;
END EL_SQL2PL_1;
BEGIN
JOB_ID_PARAMTARGET := EL_SQL2PL_1(JOB_ID_PARAMCOMPAT);
FAC_JOB_INTEGRATION.RETRIEVE_JOBS(JOB_ID_PARAM=>JOB_ID_PARAMTARGET, JOBS_PARAM=>JOBS_PARAMTARGET);
:2 := JOBS_PARAMTARGET;
END;
bind => [:1 => TipoEntrada [jobId=200], ]
客體的價值:
[DatabaseRecord(JOBS_PARAM => [])]
更新1
我嘗試了一種不同的方式,現在使用eclipselink的ScrollableCursor,我可以執行該過程並返回一個Cursor,但是當試圖通過它時,我將結果集關閉。
我嘗試了幾種方法來打開它,包括持久性單元(RESOURCE_LOCAL),但我沒有成功。
任何人有任何提示嗎?
異常[的EclipseLink-4002](Eclipse持久服務 - 2.4.2.v20130514-5956486):org.eclipse.persistence.exceptions.DatabaseException 內部異常:java.sql中。的SQLException:結果集已經關閉
EntityManagerFactory createEntityManagerFactory = Persistence.createEntityManagerFactory("localFactPU");
//EntityManager em = FJPAManager.getInstance().getEntityManagerContext("localFactPU").getEntityManager();
EntityManager em = createEntityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.getTransaction().isActive();
System.out.println(em.isOpen());
//em.getTransaction().begin();
ReadAllQuery databaseQuery = new ReadAllQuery(DBAJobsOracleEntity.class);
databaseQuery.useCursoredStream();
StoredProcedureCall calles = new StoredProcedureCall();
calles.setProcedureName("FAC_JOB_INTEGRATION.TEST_ESTEVAO");
calles.useNamedCursorOutputAsResultSet("JOBS_PARAM");
databaseQuery.setCall(calles);
databaseQuery.useCursoredStream();
databaseQuery.useScrollableCursor(1000);
//session = ((JpaEntityManager) getEntityManager().getDelegate()).getActiveSession();
//session.executeQuery(databaseQuery);
//JpaQuery queryess = (JpaQuery) ((JpaEntityManager)getEntityManager().getDelegate()).createQuery(databaseQuery);
JpaQuery queryess = (JpaQuery) ((JpaEntityManager)em.getDelegate()).createQuery(databaseQuery);
queryess.setHint(QueryHints.CURSOR, true);
queryess.setHint(QueryHints.CURSOR_INITIAL_SIZE, 2);
queryess.setHint(QueryHints.CURSOR_PAGE_SIZE, 5);
queryess.setHint(QueryHints.RESULT_SET_CONCURRENCY, ResultSetConcurrency.ReadOnly);
String resultSetType = ResultSetType.DEFAULT;
queryess.setHint(QueryHints.RESULT_SET_TYPE, resultSetType);
ScrollableCursor scrollableCursor = (ScrollableCursor)queryess.getResultCursor();
DatabaseSessionImpl databaseSession = ((JpaEntityManager)em.getDelegate()).getDatabaseSession();
scrollableCursor.setSession(databaseSession);
scrollableCursor.next();
scrollableCursor.close();