我正在开发一个使用数据库访问对象(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 <= ?");
) {
尽管我们有两个级别的关闭连接
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.