我非常希望得到你的帮助,我尝试了几件事,但我无法解决问题。
我正在使用: Eclipselink 2.42 和 Oracle 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);
PROCEDURE运行没有问题,但不返回游标值:
日志执行:
[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 Persistence Services - 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();
答案 0 :(得分:0)
你可以尝试
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");
或者在您的实体类中尝试
@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)})