Java.sql.SQLException:ORA-08103:对象不再存在于存储过程中的游标

时间:2016-04-26 14:03:52

标签: java stored-procedures cursor sqlexception

您好我有一个调用存储过程的方法,但我收到了下一个错误:

" GRAVE [cl.auter.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相同的结果。 一些建议?

2 个答案:

答案 0 :(得分:2)

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

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

executeQuery()

此外,在完全防御模式下编程将要求在返回之前恢复原始连接自动提交状态,以避免干扰数据源管理的基础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 ... } 的其他用途。我没有对上面的模型进行建模,因为数据源不应该要求它,但这可以防御DS中合理的当前或未来的错误。

答案 1 :(得分:0)

在mybatis和spring中使用CURSOR时需要考虑两件事

  1. 声明应该在一行中。仅在参数存在时中断
  2.         {call my_proc(#{paramName,jdbcType = VARCHAR,mode = IN},#{out,mode = OUT,jdbcType = CURSOR,resultMap = franApplicationSettings})}     

    1. 如果您收到此错误

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

      您必须确保使用@Transactional注释spring方法     原因是mybatis将其提供给oracle后光标引用丢失。