Файл базы данных "используется другим процессом", когда все соединения закрыты
Я разрабатываю систему, которая использует объект доступа к базе данных (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 <= ?");
) {
И хотя у нас есть два уровня для закрытия соединений
- примерочных с-ресурсы
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.