java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java.sql.SQLException:索引中丢失 IN或OUT 参数::x

解决java.sql.SQLException:索引中丢失 IN或OUT 参数::x问题

作者:bisal(Chen Liu)

这篇文章主要介绍了解决java.sql.SQLException:索引中丢失 IN或OUT 参数::x问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

java.sql.SQLException:索引中丢失 IN或OUT 参数::x

使用JDBC时,会有这么一个错误:java.sql.SQLException: 索引中丢失 IN或OUT 参数::x

如下:

示例中insertLog.execute();这行会抛出这个异常:

String logSQL = "insert into tbl_obj(id, obj, type, cont, proposer, operator, date, remark) "
                       + "values(seq_tot.nextval, ?, ?, ?, ?, ?, SYSDATE, ?)";
insertLog = conn.prepareStatement(logSQL);
insertLog.setString(2, trace.getObj());
insertLog.setString(3, trace.getType());
insertLog.setString(4, trace.getCont());
insertLog.setString(5, trace.getProposer());
insertLog.setString(6, trace.getOperator());
insertLog.setString(8, trace.getRemark());
insertLog.execute();

检索了一些帖子,对于这种问题,指出的原因很多

根据错误提示,归结为两点

(1) 索引是否有问题?(“索引中丢失”)

(2) 字段赋值是否与数据库字段类型匹配?

查看这张表的索引,这张表是以ID作为主键,没有其他索引,因此只有一个主键索引,查看状态也是VALID的,没有错误:

SQL> select index_name, status from user_indexes where table_name='TBL_OBJ_TRACE';
 
INDEX_NAME                     STATUS
------------------------------ --------
SYS_C0031302                   VALID

首先看了trace的set/get方法中对字段类型的定义,都是String,对应库中的字段类型都是VARCHAR2,没有差别。

其次再看setString,和VALUES中字段是对应的啊。

其实问题就出在这了,看下setString方法的解释:

void java.sql.PreparedStatement.setString(int parameterIndex, String x) throws SQLException
 
Sets the designated parameter to the given Java String value. The driver converts this to an SQL VARCHAR or LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends it to the database.
 
Parameters:
parameterIndex the first parameter is 1, the second is 2, ...
x the parameter value
Throws:
SQLException - if parameterIndex does not correspond to a parameter marker in the SQL statement; if a database access error occurs or this method is called on a closed PreparedStatement

可以看到第一个参数parameterIndex,参数索引,parameterIndex does not correspond to a parameter marker in the SQL statement(如果没有对应到SQL语句中的参数标识符),则会抛出SQLException异常。

SQL语句中values(seq_tot.nextval, ?, ?, ?, ?, ?, SYSDATE, ?)的参数标识符一共6个,setString同样是6个,但顺序不对,setString中第一个参数的索引序号是要和SQL语句中是一致的,并不是SQL语句中这里VALUES字段的位置,而应该是SQL语句VALUES中参数标识符的序号。

改为如下格式就对了:

String logSQL = "insert into tbl_obj(id, obj, type, cont, proposer, operator, date, remark) "
                       + "values(seq_tot.nextval, ?, ?, ?, ?, ?, SYSDATE, ?)";
insertLog = conn.prepareStatement(logSQL);
insertLog.setString(1, trace.getObj());
insertLog.setString(2, trace.getType());
insertLog.setString(3, trace.getCont());
insertLog.setString(4, trace.getProposer());
insertLog.setString(5, trace.getOperator());
insertLog.setString(6, trace.getRemark());
insertLog.execute();

总结

JDBC的这个报错,提示信息很晦涩,但这个错误感觉是属于那种碰过一次之后,基本下次就能知道错误的范围,排查起来应该也比较顺畅了。

例如:

索引是否有问题、代码中的字段类型和表中字段类型是否一致、代码中使用的参数索引和SQL语句中的参数标识符是否一致(个数、顺序等)。

好了,以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文