我在Java中遇到困难,在单独的JAR文件中提供了SQLITE数据库。 令人惊讶的是,即使在删除JAR文件,退出并重新启动程序之后,甚至在重新启动计算机之后,似乎仍然可以访问 sqlite数据库。
我正在使用Xerial驱动程序sqlite-jdbc-3.7.2.jar
(对于org.sqlite.JDBC
)
编辑:与sqlite-jdbc-3.8.6.jar
完全相同的问题。
Xerial JDBC驱动程序在这里发布:
https://bitbucket.org/xerial/sqlite-jdbc
我真的很困惑。这个特定的JDBC驱动程序是否存在某种持久性缓存?还是我一般都错过了关于JDBC的东西?
代码示例:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SqliteJDBCTest {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet rs = null;
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite::resource:jar:file:doesntexistJAR.jar!/doesntexistDB.sqlite");
System.out.println("connection = " + connection);
statement = connection.createStatement();
System.out.println("statement = " + statement);
rs = statement.executeQuery(" SELECT * FROM nonexistentTable WHERE key = 'nonexistentKey'");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
上面的代码示例显示了问题的第一步:在第一次运行时,DriverManager.getConnection(..)
按预期抛出异常:
$ java -jar sqliteJDBCTest.jar
java.sql.SQLException: failed to load jar:file:doesntexistJAR.jar!/doesntexistDB.sqlite: java.io.FileNotFoundException: doesntexistJAR.jar (Aucun fichier ou dossier de ce type)
at org.sqlite.Conn.open(Conn.java:92)
at org.sqlite.Conn.<init>(Conn.java:57)
at org.sqlite.JDBC.createConnection(JDBC.java:77)
at org.sqlite.JDBC.connect(JDBC.java:64)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at SqliteJDBCTest.main(SqliteJDBCTest.java:18)
但是,从那以后,每次运行我得到以下输出:
>java -jar sqliteJDBCTest.jar
connection = org.sqlite.Conn@3fee733d
statement = org.sqlite.Stmt@5acf9800
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such table: nonexistentTable)
at org.sqlite.DB.newSQLException(DB.java:383)
at org.sqlite.DB.newSQLException(DB.java:387)
at org.sqlite.DB.throwex(DB.java:374)
at org.sqlite.NativeDB.prepare(Native Method)
at org.sqlite.DB.prepare(DB.java:123)
at org.sqlite.Stmt.executeQuery(Stmt.java:121)
at SqliteJDBCTest.main(SqliteJDBCTest.java:23)
在此示例中,SQLException
&#34; SQL错误或缺少数据库&#34;这不是我们期待的错误!
不仅缺少数据库,而且甚至JAR文件都应该包含它!
那么getConnection()
怎么不首先抛出异常呢?
答案 0 :(得分:1)
简短回答:因为Xerial JDBC驱动程序中存在错误。
当通过调用DriverManager.getConnection(jdbc:sqlite::resource:jar:file:<local_location_of_JAR>!/<name_of_database_file>)
,请求Xerial驱动程序建立连接时,驱动程序会在Java系统属性 {{指定的临时目录上创建数据库文件的副本。 1}} 然后对此副本进行操作。
问题在于,当删除原始JAR时,驱动程序会在下次使用相同java.io.tmpdir
调用时加载副本。对我来说,这是一个错误;驱动程序至少应该检查URL指向的(可能是远程的)JAR文件是否仍然存在...
第二个问题(本文的CODE SAMPLE中描述的问题):当原始JAR文件不存在时,创建(不存在的)数据库的“ copy ”,并且使用相同的参数调用下一次getConnection()
时,驱动程序直接返回一个幻像连接到这个从未找到的空数据库......
我在Xerial JIRA网站的错误报告中提交了这个故事: https://bitbucket.org/xerial/sqlite-jdbc/issue/158/drivermanagergetconnection-not-returning