Файл базы данных «используется другим процессом», когда все соединения закрыты - PullRequest
0 голосов
/ 02 ноября 2018

Я разрабатываю систему, которая использует объект доступа к базе данных (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.
...