0

我正在开发一个系统,它使用数据库访问对象 (DAO) 在程序和数据库之间进行链接。所有连接都必须通过这个类,使用getConnection(). 但是,我有一个重置选项,它使用应用程序本身内部的一个覆盖用户文件系统中的数据库文件(即部署时在其 jar 中)。此reset()功能会导致异常,指出数据库已在使用中。

java.nio.file.FileSystemException: C:\iMProve\improveDB.accdb: The process cannot access the file because it is being used by another process.

通过研究,这意味着连接没有正确关闭。但是,如果您能发现问题所在,我将向您展示这个 DAO 类的整个代码。

public class DAO {
    private static final String dbDir = "C://iMProve";
    private static final String dbName = "improveDB.accdb";
    private static final String dbUrl = "jdbc:ucanaccess://" + dbDir + "//"+ dbName;
    private ObservableList<Connection> allConnections = FXCollections.observableArrayList();

    public DAO() { //constructor - called when object is made
        try {
            Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
        } catch(ClassNotFoundException e) {
            System.out.println("Cannot load ucanaccess driver");
            e.printStackTrace();
        }
        File directory = new File(dbDir);
        if(!directory.exists()) //create directory if not already
            directory.mkdir();
        File database = new File(dbDir + "//" + dbName);
        if(!database.exists()) { //copy the database file into user's file system - if not already
            try {
                Files.copy(DAO.class.getResourceAsStream(dbName), database.toPath(), StandardCopyOption.REPLACE_EXISTING);
            } catch(IOException ex) {ex.printStackTrace();}
        }
    }
    public void reset() {
        File database = new File(dbDir + "//" + dbName);
        try {
            Files.copy(DAO.class.getResourceAsStream(dbName), database.toPath(), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Connection getConnection() { //create a connection to the database
        Connection conn = null; 
        try {
            conn = DriverManager.getConnection(dbUrl);
        } catch (SQLException e) {
            e.printStackTrace();
        }   
        allConnections.add(conn);
        return conn;
    }
    public void closeConnections() {
        for(Connection conn: allConnections) {
            if(conn!=null) {
                try {
                    conn.close();
                    System.out.println("closed");
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

构造函数只是将数据库从应用程序复制到用户的文件系统中(如果还没有的话)。

getConnection()方法连接到数据库。

单独调用reset()会产生该错误,因此通过将连接添加到静态集合中,我们可以关闭每个连接,使用closeConnections().

注意:无论如何,这些连接应该已经关闭,因为我们总是尝试使用资源。例如:

try (
            Connection conn = dao.getConnection();
            PreparedStatement stmt = conn.prepareStatement("SELECT Title FROM Theory WHERE Grade <= ?");
    ) {

虽然我们有两个级别来关闭连接

  1. 尝试资源
  2. closeConnections()方法

他们仍然无效。当调用 closeConnections() 时,我们仍然得到输出

closed
closed

即使在 try-with-resources 块中使用了连接。即使使用 closeConnections(),我们仍然会遇到相同的错误:

java.nio.file.FileSystemException: C:\iMProve\improveDB.accdb: The process cannot access the file because it is being used by another process.
4

0 回答 0