jpa 为什么我对oracle中存储过程的java调用的结果为空?

pftdvrlh  于 2022-11-14  发布在  Oracle
关注(0)|答案(1)|浏览(202)

当使用sqlplus调用时,我有以下过程:

SQL> exec test_proc('test_search', :varcursor);

工作得很好,并给出了预期的结果(表中的id列表)。

CREATE OR REPLACE PROCEDURE test_proc
    (search_term IN varchar2,
    c1 OUT SYS_REFCURSOR)
AS
BEGIN
    OPEN c1 for
    select test.id 
        from test_table t
        WHERE JSON_TEXTCONTAINS(t.test_col, '$', search_term);
    DBMS_SQL.RETURN_RESULT(c1);
END test_proc;

然而,如果从我的Spring应用程序中使用JPA/eclipselink调用,结果总是null。

StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("test_proc")
            .registerStoredProcedureParameter(1, String.class, ParameterMode.IN)
            .registerStoredProcedureParameter(2, Class.class, ParameterMode.REF_CURSOR)
            .setParameter(1, "test");
    // execute SP
    storedProcedure.execute(); --> true
    List<Object[]> res = storedProcedure.getResultList();

直接在jdbc驱动程序上它也是空的。

Connection conn = DataSourceUtils.getConnection(dataSource);
    CallableStatement st = null;
    ResultSet rs = null;
    try {
        st = conn.prepareCall( "{call test_proc(?,?)}" );
        st.setString(1, "test");
        st.registerOutParameter( 2, OracleTypes.CURSOR );
        boolean hadResults = st.execute();
        System.out.println( hadResults ); --> always false
        
        rs = (ResultSet) st.getObject(2);
        while ( rs.next() )
        {        
            System.out.println( rs.getInt(1) );
        }
        st.close();
    } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
zc0qhyus

zc0qhyus1#

这里似乎发生了一些奇怪的事情。
首先,您的存储过程很奇怪,因为它试图同时以OUT参数和隐式结果的形式返回来自游标的数据。(a)通过OUT参数或(B)通过隐式结果,但不能同时通过这两种方式。(我的建议是通过OUT参数返回它,方法是删除对DBMS_SQL.RETURN_RESULT的调用。)
但是,如果您没有更改存储过程的选项,那么您将不得不接受它返回的隐式结果。似乎通过隐式结果返回游标会覆盖通过OUT参数返回游标。
第二件奇怪的事情是,OracleJDBC驱动程序似乎并不完全遵循隐式结果的JDBC标准。(Oracle在这里提供了示例代码),而JDBC标准规定使用.getMoreResults()返回后续结果,建议在调用.getMoreResults()之前应该可以获得第一个结果。
尝试调用st.getMoreResults(),检查它是否返回true,然后通过调用st.getResultSet()获取结果集。

Connection conn = DataSourceUtils.getConnection(dataSource);
    CallableStatement st = null;
    ResultSet rs = null;
    try {
        st = conn.prepareCall( "{call test_proc(?,?)}" );
        st.setString(1, "test");
        st.registerOutParameter( 2, OracleTypes.CURSOR );
        boolean hadResults = st.execute();
        System.out.println( hadResults ); // --> always false
        
        System.out.println(st.getMoreResults()); // printed 'true' for me.
        rs = st.getResultSet();
        while ( rs.next() )
        {        
            System.out.println( rs.getInt(1) );
        }
        st.close();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

相关问题