Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么删除SQLite数据库JAR后java.sql.DriverManager.getConnection()仍在工作?_Java_Sqlite_Jdbc_Jar - Fatal编程技术网

为什么删除SQLite数据库JAR后java.sql.DriverManager.getConnection()仍在工作?

为什么删除SQLite数据库JAR后java.sql.DriverManager.getConnection()仍在工作?,java,sqlite,jdbc,jar,Java,Sqlite,Jdbc,Jar,我在Java中使用单独JAR文件中提供的SQLITE数据库时遇到困难。 令人惊讶的是,即使在删除JAR文件、退出并重新启动程序之后,甚至在重新启动机器之后,sqlite数据库似乎也会被访问 我正在使用Xerial驱动程序sqlite-jdbc-3.7.2.jar(用于org.sqlite.jdbc)。 编辑:与sqlite-jdbc-3.8.6.jar的问题非常相似。 Xerial JDBC驱动程序发布于此处: 我真的很困惑。这个特定的JDBC驱动程序是否有某种持久缓存?或者是我在JDBC方面

我在Java中使用单独JAR文件中提供的SQLITE数据库时遇到困难。 令人惊讶的是,即使在删除JAR文件、退出并重新启动程序之后,甚至在重新启动机器之后,sqlite数据库似乎也会被访问

我正在使用Xerial驱动程序
sqlite-jdbc-3.7.2.jar
(用于
org.sqlite.jdbc
)。
编辑:
sqlite-jdbc-3.8.6.jar的问题非常相似。
Xerial 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)
在本例中,
SQLException
“SQL错误或缺少数据库”不是我们期望的错误

不仅数据库丢失了,甚至连应该包含它的JAR文件也丢失了!
那么为什么
getConnection()
一开始就不会抛出异常呢?

简单回答:因为Xerial JDBC驱动程序中有一个bug

当通过调用
DriverManager.getConnection(jdbc:sqlite::resource:jar:file:!/)
向Xerial驱动程序请求连接时,驱动程序在Java系统属性
Java.io.tmpdir
指定的临时目录上创建数据库文件的副本,然后对该副本进行操作

问题是,当原始JAR被移除时,驱动程序在下次使用相同的
getConnection()
调用时加载副本。对我来说,这是一个错误;驱动程序至少应该检查URL指向的(可能是远程)JAR文件是否仍然存在

第二个问题(本文代码示例中描述的问题):当原始JAR文件不存在时,将创建(不存在的)数据库的“副本”,下次使用相同的参数调用getConnection(),驱动程序直接返回一个到这个空数据库的虚拟连接,而这个空数据库从未找到

我在Xerial JIRA网站上的bug报告中提交了这个故事:

您是否尝试过在数据库中插入内容,并在下次尝试时将其读回?如果这是可行的,DB是在某处创建的。是的,我有。然后,在删除数据库后,我仍然可以看到我插入的内容。注意:我使用Sourceforge的sqlite db编辑器在我的应用程序之外手动插入了JAR文件。很明显,JAR文件或它的另一个版本在类路径上的某个地方仍然可用。但是JAR已从文件系统中正确删除。所以我真的很困惑,Java已经向您保证它仍然找到了一个。继续找。
>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)