【发布时间】:2014-04-01 17:59:25
【问题描述】:
我遇到了以下问题:我正在尝试使用以下代码将数据(在本例中为用户名)插入到表中:
void AddNewUser(String name, Connection conn){
if(ret == null){
ret = new DB_Retriever(conn);
}
if(!ret.UserExists(name, conn)){
try{
Statement stm = conn.createStatement();
stm.executeUpdate(DB_OperationalData.insert_new_user[0][0] + name + DB_OperationalData.insert_new_user[0][1]);
stm.executeUpdate(DB_OperationalData.insert_new_user[1][0] + name + DB_OperationalData.insert_new_user[1][1]);
stm.close();
}
catch(SQLException e){
e.printStackTrace();
}
}
}
顺便说一句:我在 catch 子句中放什么绝对无关紧要,我放在那里的任何东西都不会被执行。为了说明一切,这里是 DB_OperationalData.insert_new_user 字符串数组的内容:
public static final String[][] insert_new_user = {
{"INSERT INTO User (Username, Status) VALUES ('","','IN');"},
{"INSERT INTO Statistics (Player_ID) SELECT ID FROM User WHERE Username='","';"}};
第二条语句应该复制插入的用户ID,并将其放入Statistics表的Player_ID字段中(表用户ID是一个自动编号的字段)。
我得到的例外是:
Error while processing the query: java.sql.SQLException: ResultSet closed
有趣的是,它可以正常工作并且正确添加了数据,但我根本不希望抛出任何异常。
这是我得到的控制台输出:
This is 'data' Package Testing class
Connection to the database established.
The number of tables existing in the database is: 0
All the queries have been processed successfully
Adding new users:
Error while processing the query: java.sql.SQLException: ResultSet closed
异常上面的所有行都是我自己的打印输出,所以我知道实际发生了什么。
[编辑]
我已将代码更改为使用 PreparedStatement 而不是普通的 Statement,当前的 try 子句如下所示:
PreparedStatement pstm = conn.prepareStatement(DB_OperationalData.insert_new_user[0]);
pstm.setString(1, name);
pstm.addBatch();
conn.setAutoCommit(false);
pstm.executeBatch();
conn.setAutoCommit(true);
pstm.close();
并且输出是(仍然不管catch子句的内容):
This is 'data' Package Testing class
Connection to the database established.
The number of tables existing in the database is: 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at org.sqlite.PrepStmt.batch(PrepStmt.java:173)
at org.sqlite.PrepStmt.setString(PrepStmt.java:254)
at data.DB_Writer.AddNewUser(DB_Writer.java:28)
at data.DataHandler.AddNewUser(DataHandler.java:94)
at data.Tester.main(Tester.java:18)
All the queries have been processed successfully
Adding new users:
Error while processing the query: java.sql.SQLException: ResultSet closed
[编辑 2] 关于原始版本,当我删除 stm.close();绝对没有区别,我仍然得到 'ResultSet closed' 异常。
[编辑 3] 以下是调用上述方法的代码:
public void AddNewUser(String username)throws IllegalUsernameException{
if(username.length()==0 || username.length()>20){
throw new IllegalUsernameException();
}
writer.AddNewUser(username, conn);
}
通过这个类建立与数据库的连接:
class DB_Connection {
public static Connection getConnection(){
Connection conn = null;
try{
Class.forName("org.sqlite.JDBC");
}
catch(ClassNotFoundException e){
log("Error while loading the database driver: " + e);
return null;
}
try{
conn = DriverManager.getConnection("jdbc:sqlite:database.db");
}
catch(SQLException e){
log("Unable to connect to the database: " + e);
return null;
}
return conn;
}
public static void log(String msg){
System.out.println(msg);
}
}
正在检查现有用户名的 DB_Retriever 方法:
boolean UserExists(String name, Connection conn){
String result = "";
try{
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery(DB_OperationalData.user_exists[0] + name + DB_OperationalData.user_exists[1]);
result = rs.getString("Username");
}
catch(SQLException e){
System.out.println("Error while processing the query: " + e);
}
if(result.equals(name)){
return true;
}
return false;
}
【问题讨论】:
-
请添加堆栈跟踪。还要检查抛出异常的确切位置(类和行号)。为了澄清,异常是在空的 catch 块到位的情况下引发的?那么它不能是由您显示的代码引起的。根据定义,catch 块将阻止异常传播。其他可能有助于找到原因的有趣问题:连接是在哪里以及如何创建的?你使用连接池吗? DB_Retriever 在做什么?你为什么不结束声明?请承诺在修复此错误后立即阅读有关 java.sql.PreparedStatement 的内容!
-
catch 块为空时抛出异常,非空时也会抛出异常。连接是在一个单独的类中创建的,我将添加它。 DB_Retriever 只是从数据库中读取数据,不会抛出任何异常。在这种情况下,它会检查给定的用户名是否已经存在于数据库中。更新代码以反映建议。
-
就目前而言,控制台输出对我们来说毫无用处,因为我们不知道您的代码。输出中引用的异常 cannot 从您发布的 try-catch 块内的代码中抛出。在代码中的其他地方捕获了 SQLException 并打印了 exception.message() 值。找到那个 catch 块并将其更改为至少打印一个堆栈跟踪。然后检查堆栈跟踪中的类和行号。如果您无法弄清楚,请使用触发异常的代码部分更新您的问题。提示:DML 语句不创建结果集。 SELECT 可以。
-
@Pyranja 我确实意识到 DML 语句不应该创建任何结果集,这也是我对这个异常感到困惑的原因。标准的 executeUpdate 方法仅返回一个整数,其中包含已更改的行数。我已经插入了一些 println 语句,结果现在更加有趣:当执行 try 块时,我们最终得到:ResultSet 异常,我的字符串在声明 PreparedStatement 之后直接打印,并分配了插入查询,然后是 ArrayOutOfBoundsException被抛出并且这个异常指向 PrepStmt.java
标签: java sql sqlite exception resultset