我有一个
java.sql.SQLException 错误:准备好的语句已经完成
,当我第二次调用相同的preparedStatement时会发生这种情况.我在一种方法中称呼它.
这是数据库Java类(相关部分)
//create the charge table. (ps is PreparedStatement)
try{
statement.executeUpdate("CREATE TABLE charge(username TEXT NOT NULL, date DATETIME DEFAULT CURRENT_TIMESTAMP, charge REAL, PRIMARY KEY(username, date));");
} catch (SQLException ex) {
System.out.println("charge table creation failed. exception" + ex);
}
Run Code Online (Sandbox Code Playgroud)
创建费用的方法:
public void createCharge(String username, double amount){
try {
System.out.println(username + amount);
ps = connection.prepareStatement("INSERT INTO charge VALUES(?, ?, ?);");
ps.setString(1, username);
ps.setDate(2, DateConvert.toSQLDate(Date.valueOf(LocalDate.MIN)));
ps.setDouble(3, amount);
ps.executeUpdate();
ps.clearParameters();
System.out.println("Complete");
} catch (SQLException ex) {
Logger.getLogger(MontsRentalDatabase.class.getName()).log(Level.SEVERE, null, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
这是在创建费用的类中:
public void createCharge(String username, double amount){
try {
System.out.println(username + amount);
ps = connection.prepareStatement("INSERT INTO charge VALUES(?, ?, ?);");
ps.setString(1, username);
ps.setDate(2, DateConvert.toSQLDate(Date.valueOf(LocalDate.MIN)));
ps.setDouble(3, amount);
ps.executeUpdate(); //Line 170
ps.clearParameters();
System.out.println("Complete");
} catch (SQLException ex) {
Logger.getLogger(MontsRentalDatabase.class.getName()).log(Level.SEVERE, null, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
将普通日期转换为sqldate的类:public class DateConvert {
public static java.sql.Date toSQLDate(java.util.Date date){
return new java.sql.Date(date.getTime());
}
public static java.util.Date toJavaDate(java.sql.Date date){
return new java.util.Date(date.getTime());
}
}
Run Code Online (Sandbox Code Playgroud)
该错误在创建费用的第170行,即ps.executeUpdate运行时.第一次运行成功,第二次运行失败.日志:
450100.0
Complete
450150.0
SEVERE: null
java.sql.SQLException: The prepared statement has been finalized
at org.sqlite.core.NativeDB.throwex(NativeDB.java:429)
at org.sqlite.core.NativeDB.reset(Native Method)
at org.sqlite.core.DB.executeUpdate(DB.java:878)
at org.sqlite.jdbc3.JDBC3PreparedStatement.executeUpdate(JDBC3PreparedStatement.java:99)
at server.RentalDatabase.createCharge(RentalDatabase.java:170)
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助,J
我相信这是SQLite JDBC驱动程序3.14.2.1版中的一个错误.
在我看来,你得到一个唯一的约束违规异常,但SQLite JDBC驱动程序试图报告此异常并试图抛出一些其他异常而绊倒自己.
如果我尝试多次插入相同的数据,例如通过重新运行代码,我能够使用sqlite-jdbc版本3.14.2.1重现您的异常.我将SQLite JDBC驱动程序降级为3.8.11.2,运行代码后出现以下异常:
java.sql.SQLException: [SQLITE_CONSTRAINT] Abort due to constraint violation (UNIQUE constraint failed: charge.username, charge.date)
at org.sqlite.core.DB.newSQLException(DB.java:890)
at org.sqlite.core.DB.newSQLException(DB.java:901)
at org.sqlite.core.DB.execute(DB.java:810)
at org.sqlite.core.DB.executeUpdate(DB.java:847)
at org.sqlite.jdbc3.JDBC3PreparedStatement.executeUpdate(JDBC3PreparedStatement.java:86)
at com.example.MontsRentalDatabase.createCharge(MontsRentalDatabase.java:40)
at com.example.Main.main(Main.java:17)
Run Code Online (Sandbox Code Playgroud)
当然,重新运行程序时,我试图插入的数据已经在表中.因此,可以预期唯一的约束违规.
然后我添加了这条线
statement.execute("DROP TABLE IF EXISTS charge");
Run Code Online (Sandbox Code Playgroud)
to createChargeTable(),在创建表的行之上.然后使用任一版本的SQLite JDBC驱动程序多次成功运行代码.
现在已在sqlite-jdbc 3.15.1版本中修复了此错误,因此修复程序将升级到此版本或更高版本.