I would like your help a lot, I tried several things and I could not solve my problem.
I'm using: Eclipselink 2.42 and Oracle 11
I need to execute a procedure that returns a SYS_REFCURSOR , but I can not execute this procedure using eclipselink (JPA) , I tried it in several ways and it seems to me that the API is not identifying the SYS_REFCURSOR type.
Could someone please help me, I'm already out of ideas, to make this work
This is my procedure:
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;
And Here is some Tests with the result:
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);
My error:
[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()
Second Test:
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);
Error Result:
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)
Now I create a 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");
}
}
First Test:
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);
The PROCEDURE is Run without problems, but not return the cursor values:
Log Execution:
[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], ]
Object Value:
[DatabaseRecord(JOBS_PARAM => [])]
Update 1
I'm trying a different way, now using the ScrollableCursor of eclipselink, I can execute the procedure and return a Cursor, however when trying to go through it I'm having a result set close.
I tried several ways to make it open, including having a Persistence Unit (RESOURCE_LOCAL), but I was not successful.
Anyone have any tips?
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLException: Result set already closed
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();
Can you try as
StoredProcedureQuery query = em.createNamedStoredProcedureQuery("RETRIEVE_JOBS");
query.setParameter("JOB_ID_PARAM", 9999);
query.execute();
List<YourClass.class> result = (List<YourClass.class>)query.getOutputParameterValue("JOBS_PARAM");
Or in your Entity class try as
@NamedStoredProcedureQuery(name = "findJobs",
procedureName = "RETRIEVE_JOBS",
resultClass = <YourEntityClassName>.class,
parameters = {
@StoredProcedureParameter(queryParameter = "JobId", name = "JOB_ID_PARAM",
direction = Direction.IN,
type = String.class)
,
@StoredProcedureParameter(queryParameter =
"my_cursor",
name =
"JOBS_PARAM",
direction =
Direction.OUT_CURSOR)})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.