关闭所有连接后,数据库文件“正在被另一个进程使用”

时间:2018-11-01 21:25:05

标签: java database connection data-access-object

我正在开发一个使用数据库访问对象(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-with-resources,因此无论如何这些连接都应该已经关闭。 例如:

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.

0 个答案:

没有答案