2017-05-05 36 views
0

我希望得到您的幫助,我嘗試了幾件事情,但無法解決我的問題。如何使用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(); 

回答

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)}) 
相關問題