Java.sql.SQLException: ORA-08103: 对象在存储过程中不再存在游标
Java.sql.SQLException: ORA-08103: object no longer exists cursor in stored procedure
您好,我有一个调用存储过程的方法,但出现下一个错误:
"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 结果相同。
有什么建议吗?
问题是您的存储过程返回的游标仅在 SP 本身运行的同一事务中有效。如果您的连接在自动提交模式下运行,则该事务在 executeQuery()
方法 returns 之前结束。其他类型的out参数在事务结束后仍然存在,但游标不再有效
您可以通过手动控制事务边界来解决此问题。为此,您必须确保连接未处于自动提交模式,并且您必须确保在您的方法returns之前手动提交事务或将其回滚。这是一个大纲:
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 中当前或未来可能出现的错误。
在 mybatis 中使用 CURSOR 时需要考虑两件事 spring
- 声明应在一行中。仅在存在参数时中断
{ call my_proc(#{paramName,jdbcType=VARCHAR,mode=IN},#{out, mode=OUT, jdbcType=CURSOR,resultMap=franApplicationSettings})}
如果你遇到这个错误
ORA-08103: 对象在存储过程中不再存在游标
您必须确保 spring 方法使用 @Transactional 注释
原因是mybatis给oracle后游标引用丢失了
您好,我有一个调用存储过程的方法,但出现下一个错误:
"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 结果相同。 有什么建议吗?
问题是您的存储过程返回的游标仅在 SP 本身运行的同一事务中有效。如果您的连接在自动提交模式下运行,则该事务在 executeQuery()
方法 returns 之前结束。其他类型的out参数在事务结束后仍然存在,但游标不再有效
您可以通过手动控制事务边界来解决此问题。为此,您必须确保连接未处于自动提交模式,并且您必须确保在您的方法returns之前手动提交事务或将其回滚。这是一个大纲:
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 中当前或未来可能出现的错误。
在 mybatis 中使用 CURSOR 时需要考虑两件事 spring
- 声明应在一行中。仅在存在参数时中断
{ call my_proc(#{paramName,jdbcType=VARCHAR,mode=IN},#{out, mode=OUT, jdbcType=CURSOR,resultMap=franApplicationSettings})}
如果你遇到这个错误
ORA-08103: 对象在存储过程中不再存在游标
您必须确保 spring 方法使用 @Transactional 注释 原因是mybatis给oracle后游标引用丢失了