我正在开发一个系统,它使用数据库访问对象 (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.