我正在编写一个Java类,通过迭代将数据插入到数据库中。虽然我现在可以插入数据,但我正在努力处理Oracle错误。在这种情况下,我故意通过尝试插入重复的主键来创建主键约束错误(我已使用与我尝试使用Java插入的条目预先加载数据库)
正如所料,我得到了" ORA-00001:唯一约束"。但是,我遇到的问题是,经过300次迭代后,我遇到了一个新的错误:" ORA-01000:超出最大打开游标"
我想问题是每个失败的executeUpdate()
都会打开游标。
我通过在错误的捕获上包含close()
语句暂时解决了这个问题。但是,我想知道:
executeUpdate()
是否应关闭光标? 我的Java代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestOracleError {
private static Connection conn;
public static void main(String[] args) {
//Connect
try {
conn = DriverManager.getConnection("jdbc:oracle:thin:"+
"@XXX.XXX.XXX.XXX:1521:XXXX", "XXXX", "XXXX");
}
catch(SQLException e) {
System.err.println(e.getMessage());
}
//Iterate insert
for(int i=1; i<5000; i++){
PreparedStatement pstmt=null;
try {
//Deliberate error on the SQL (Primary Key Constraint)
pstmt = conn.prepareStatement("INSERT INTO DUMMY (ID) VALUES "
+"('"+i+"')");
pstmt.executeUpdate();
pstmt.close();
}
catch(Exception e) {
System.err.println("DB Error on iteration "+i+": " +
e.getMessage());
//If I add the following line then I can close the error!
//try {pstmt.close();} catch (Exception e1) {}
}
}
}
}
答案 0 :(得分:2)
最后使用或尝试使用资源。
try {
//Deliberate error on the SQL (Primary Key Constraint)
// Only set the variable in the loop
pstmt.setInt(1, i);
pstmt.executeUpdate();
} catch (Exception e) {
System.err.println("DB Error on iteration "+i+": " +
e.getMessage());
//If I add the following line then I can close the error!
//try {pstmt.close();} catch (Exception e1) {}
}
finally
{
pstmt.close();
}
或
try (Connection con = DriverManager.getConnection(myConnectionURL);
PreparedStatement ps = con.prepareStatement(sql);) {
......
}
} catch (SQLException e) {
e.printStackTrace();
}
答案 1 :(得分:1)
如果需要插入多行,则在循环外部创建预准备语句,并仅设置循环内的值。
// Moved outside
PreparedStatement pstmt=null;
// Using the question mark as a placeholder for a variable
pstmt = conn.prepareStatement("INSERT INTO DUMMY (ID) VALUES (?)");
for (int i = 1; i < 5000; i++) {
try {
//Deliberate error on the SQL (Primary Key Constraint)
// Only set the variable in the loop
pstmt.setInt(1, i);
pstmt.executeUpdate();
} catch (Exception e) {
System.err.println("DB Error on iteration "+i+": " +
e.getMessage());
//If I add the following line then I can close the error!
//try {pstmt.close();} catch (Exception e1) {}
}
}
pstmt.close(); // Moved out of loop
注意:如果发生异常,您的代码不会关闭pstmt
。所以声明仍然开放。这可能会产生太多打开游标的问题。
通常,最佳解决方案是关闭finally
块中的资源或使用尝试使用资源声明
答案 2 :(得分:0)
我想问题是每个失败的executeUpdate()都会保持游标打开。
不,问题是如果发生PreparedStatements
,您就不会关闭SQLException
。
失败的
executeUpdate()
是否应该关闭光标?
没有
有没有更好的方法可以关闭Exception上的游标?
关闭PreparedStatement
块中的finally
,或使用try-with-resources语法。
为什么会返回null异常?
它没有。它使用null 消息抛出异常。
您应该调查批次,而不是准备5000 PreparedStatements
。