1. Java大量写入oracle时容易出现此错。经过此错,也触动自己要深刻理解 java 的 prepareStatement 等对象,及数据库的连接与释放。
2. 原因:经常会出现在 for 循环中进行数据库写入操作。
3. 案例:我在将Excel导入到Oracle数据库中时,在遍历Excel的每一行数据时,都执行了语句
conn.prepareStatement(sql);
结果每次执行到2000行时出现游标错误。更正后,一次顺利导入5000条数据。
class myCode{ Connection con = null; PreparedStatement pre = null; ResultSet result = null; void readExcel(){ for(...) for(...) update(); } void update(){ String sql = "update myTabe set A=? where id=?"; pre = conn.prepareStatement(sql); pre.setString(1,A); pre.setLong(2, 123); pre.executeUpdate(); //报错 } static void main(String[] args){ connDB() initDbObj() readExcel()
close(DbOjb)()//close ps,rs
closeDB()//close conn
} }
正确的 update()函数应该如下:(2017年5月26日 更新,下方法也不是很好的实践代码,最好的做法将conn.prepareStatement提出到for循环外)
//正确代码 void update(){ String sql = "update myTabe set A=? where id=?"; pre = conn.prepareStatement(sql); pre.setString(1,A); pre.setLong(2, 123); pre.executeUpdate(); //重点 if( pre != null ){ pre.close(); } } //pre对象用完必须立马关闭,不要放到最后和 conn一起关闭。 //否则,每次pre被设置一次,就会申请一个游标,一般游标才300个 //很快就会报错。
——————————————————————
2017年5月26日 更新:上面代码有问题。
String sql = "update myTabe set A=? where id=?";
pre = conn.prepareStatement(sql);
根本不应该放在 for 循环内部。应提出到 for 循环之外的上面。
更合适的代码应该为:
class myCode{ Connection con = null; PreparedStatement pre = null; ResultSet result = null; String sql = "update myTabe set A=? where id=?"; pre = conn.prepareStatement(sql); void readExcel(){ for(...) for(...) update(); } void update(){ pre.setString(1,A); pre.setLong(2, 123); pre.executeUpdate(); } static void main(String[] args){ connDB() initDbObj() readExcel()
close(DbOjb)()//close ps,rs
closeDB()//close conn
} }
或者使用较复杂的 “PreparedStatement的批量提交功能” 。