2016-04-26 283 views
1

你好,我有一个调用存储过程的方法,但我得到了一个错误:值java.sql.SQLException:ORA-08103:对象不再存在于存储过程光标

“严重[CL。 acess.sictrav.daos.sictrav.ControladorDao](MSC服务线程1-1)java.sql.SQLException:ORA-08103:对象不再存在 :java.sql.SQLException:ORA-08103:对象不再存在“

引用此行ResultSet rs =(ResultSet)cStmt.getObject(3);

我的代码是

public List obtenerBitsEstadoDao(Controlador controlador) { 
    DBSictrav conn = new DBSictrav(); 
    List bitsestado = new ArrayList(); 
    Connection connection = null; 
    try { 
     connection = conn.getConection(""); 
     String query = "{ call pkg_plan_sic.pg_obt_bit_est_crc_ctl(?,?,?,?,?)}"; 
     try (CallableStatement cStmt = connection.prepareCall(query)) { 
      cStmt.setString(1, "CT"); 
      cStmt.setInt(2, controlador.getId()); 
      cStmt.registerOutParameter(3, OracleTypes.CURSOR); 
      cStmt.registerOutParameter(4, OracleTypes.NUMBER); 
      cStmt.registerOutParameter(5, OracleTypes.VARCHAR); 
      cStmt.executeQuery(); 
      if (cStmt.getInt(4) == 0) { 
       try 
       { 
        ResultSet rs = (ResultSet)cStmt.getObject(3); 
        while (rs.next()) { 
         BitEstado bc = new BitEstado(rs.getString("BIT_CRUCE")); 
         bc.setFaseReal(rs.getString("BIT_CONTROLADOR")); 
         bc.setPosicion(rs.getInt("POSICION")); 
         bc.setControlador(controlador); 
         bitsestado.add(bc); 
        } 
       } catch (Exception e) { 
        logger.log(Level.SEVERE, e.toString(), e); 
       } 
      } 
      else 
      { 
       throw new SictravDaoException((String) cStmt.getObject(5), cStmt.getInt(4)); 
      } 
     } catch (Exception e) { 
      logger.log(Level.SEVERE, e.toString(), e); 
     } 
    } catch (Exception e) { 
     logger.log(Level.SEVERE, e.toString(), e); 
    } finally { 

     try { 
      connection.close(); 
     } catch (SQLException ex) { 
      Logger.getLogger(PlanDao.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
    return bitsestado; 
} 

存储过程

procedure pg_obt_bit_crc_ctl(
         p_tipo  in varchar2, 
         p_id  in number, 
         p_cur_lis out cur_ref, 
         p_cod_err out number, 
         p_des_err out varchar2) is 


-- 
    v_string varchar2(32000); 
    v_ind_whe boolean := false; 
    v_num_lin varchar2(10); 
    -- 
    cursor bit_por_cr is 
    select distinct c.id_cruce, 
      t.id_masccontrol, 
      16 - instr(dec2bin(bit00), '1') + 1 F1 
      c.codigo codigo 
     from tbl_mascara_control m, 
      tbl_controlador  t, 
      tbl_cruce   c 
    where m.id_masccontrol = t.id_masccontrol 
     and c.id_controlador = t.id_controlador 
      and c.id_cruce = p_id; 
    -- 
    cursor bit_por_ct is 
     select t.id_controlador id_cruce, 
      t.id_masccontrol, 
      16 - instr(dec2bin(bit00), '1') + 1 F1, 
      16-instr(dec2bin(bit08),'1')+1 RR 
      //more similar lines 
     from tbl_mascara_control m, 
      tbl_controlador t 
     where m.id_masccontrol = t.id_masccontrol 
     and t.id_controlador = p_id; 
    -- 
    v_fase_ini  number; 
    v_num_ctl  number; 
    v_num_fase  number; 
    v_ind_fase_check number; 
    posIni   number; 
    posFin   number; 
    v_idx_pal  number; 
    v_cnt   number; 
    v_num_paralelo number; 
    -- 
    begin 
    -->Borramos los datos de la tabla temporal orientada a la transaccion... 
    commit; 
-- 

if p_tipo = 'CT' then 
    -- 
    for c in bit_por_ct loop 

     if (c.f1 is not null) then 
      insert into tbl_tmp_bits_cruce(id_cruce, bit_cruce, bit_controlador, posicion) values(c.id_cruce, 'F1', 'F1', c.F1); 
     end if; 
     //More similar lines ... 

     if (c.PR1 is not null) then 
      insert into tbl_tmp_bits_cruce(id_cruce, bit_cruce, bit_controlador, posicion) values(c.id_cruce, 'PR1', 'PR1', c.PR1); 
     end if; 

     if (c.PR2 is not null) then 
      insert into tbl_tmp_bits_cruce(id_cruce, bit_cruce, bit_controlador, posicion) values(c.id_cruce, 'PR2', 'PR2', c.PR2); 
     end if; 

     if (c.PR3 is not null) then 
      insert into tbl_tmp_bits_cruce(id_cruce, bit_cruce, bit_controlador, posicion) values(c.id_cruce, 'PR3', 'PR3', c.PR3); 
     end if; 

     if (c.PR4 is not null) then 
      insert into tbl_tmp_bits_cruce(id_cruce, bit_cruce, bit_controlador, posicion) values(c.id_cruce, 'PR4', 'PR4', c.PR4); 
     end if; 

     -- 
     if (c.RR is not null) then 
      insert into tbl_tmp_bits_cruce(id_cruce, bit_cruce, bit_controlador, posicion) values(c.id_cruce, 'RR', 'RR', c.RR); 
     end if; 
     -- 
     // More similar ifs 
     -- 
    end loop; 
end if; 
-- 
open p_cur_lis for 
    select b.id_cruce, b.bit_cruce, b.bit_controlador, b.posicion,c.codigo 
    from tbl_tmp_bits_cruce b,tbl_cruce c 
    where b.id_cruce=c.id_cruce(+) 
    order by b.posicion ; 
-- 
--> ahora recorremos el cursor... 
v_num_lin := '60'; 
p_cod_err := 0; 
p_des_err := ''; 
-- 
exception 
    when others then 
     p_cod_err := -20000; 
     p_des_err := 'Error al obtener Bits por cruce o controlador'; 
end pg_obt_bit_crc_ctl; 

我得到这个错误,我不知道为什么或如何解决它。我试着用ojdbc6和ojdbc14得到相同的结果。 一些建议?

+0

如果您在执行调用之前关闭连接上的autoCommit('connection.setAutoCommit(false)'),它会有帮助吗? –

+0

它作为一种魅力。但如果我没有记错,我之前尝试过,并且在某处发生了交易错误。 – Jebus

+0

如果您禁用autoCommit,那么您还必须记住完成后手动提交或回滚事务。恢复最初的'autoCommit'状态可能也是一个好主意 - 不管是什么;请参阅'Connection.getAutoCommit()' - 在允许连接的引用转义之前。 –

回答

1

问题是存储过程返回的游标仅在SP本身运行的同一事务中有效。如果您的连接以自动提交模式运行,则该事务在executeQuery()方法返回之前结束。其他类型的Out参数在事务结束时仍然存在,但游标不再有效。

您可以通过手动控制事务边界来解决此问题。为此,您必须确保连接不处于自动提交模式,您必须确定手动提交事务或在方法返回之前将其回滚。这里有一个轮廓:

try { 
    Connection connection = conn.getConnection(); 

    try { 
     CallableStatement cStmt; 

     connection.setAutoCommit(false); 

     cStmt = connection.prepareCall(query); 
     // ... register parameters ... 

     try { 
      cStmt.executeQuery(); 

      // ... extract and process SP out parameters ... 

      connection.commit(); 
     } catch (Exception e) { 
      connection.rollback(); 
      // ... other handling ... 
     } 
    } finally { 
     connection.close(); 
    } 
} catch (SQLException e) { 
    // handle it ... 
} 

此外,节目完全防御模式将要求在返回前恢复原来的连接自动提交状态,以避免与您的数据源管理的基础Connection的其他用途的干扰。我没有对上面的模型进行建模,因为数据源不需要它,但这可以防范DS中可能的当前或未来错误。

0

你必须考虑两件事情在MyBatis的春季

  1. 与CURSOR工作时,声明应该是在一行。打破只有当参数存在

{调用MY_PROC(#{PARAMNAME,jdbcType为VARCHAR,模式= IN},#{出来,模式= OUT,jdbcType为CURSOR,结果映射= franApplicationSettings})}

  • 如果你得到这个错误

    ORA-08103:对象不再存在光标在存储过程中

    你必须保证弹簧方法标注了@交易al 原因是游标引用在mybatis提供给oracle后丢失了。