在Windows计算机上为Derby Embedded数据库调用shutdown = true时,我无法删除system directory。
下面是我面临挑战的一个最小例子:
package derbytest;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author aelder
*/
public class DerbyTest {
private static final String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
private static final String CONN_URL = "jdbc:derby:EmbeddedDBAudit";
private static File derbySystemFolder;
private static final String USER_HOME_DIR = System.getProperty("user.home", ".");
public static Connection getConnection(boolean createDatabase) throws SQLException {
return DriverManager.getConnection(CONN_URL + (createDatabase ? ";create=true" : ""));
}
public static void shutdownConnectionAndCleanup() {
try {
DriverManager.getConnection(CONN_URL + ";shutdown=true");
} catch (SQLException ex) {
if (!ex.getSQLState().equals("08006")) {
ex.printStackTrace();
}
}
deleteFolder(derbySystemFolder);
}
public static void deleteFolder(File folder) {
File[] files = folder.listFiles();
if (files != null) { //some JVMs return null for empty dirs
for (File f : files) {
if (f.isDirectory()) {
deleteFolder(f);
} else {
f.delete();
}
}
}
folder.delete();
}
public static void setDerbyHome() {
setDatabaseFile("");
int index = 1;
while (derbySystemFolder.exists()) {
setDatabaseFile(String.valueOf(index++));
}
// Set the db system directory.
System.setProperty("derby.system.home", derbySystemFolder.getAbsolutePath());
}
private static void setDatabaseFile(String auditFolderCount) {
String databaseFilePATH = USER_HOME_DIR + File.separator + ".EmbeddedDBAudit" + auditFolderCount;
derbySystemFolder = new File(databaseFilePATH);
derbySystemFolder.deleteOnExit();
}
public static void initDerbyHomeAndDriver() {
setDerbyHome();
initDerbyDriverInstance();
}
public static void initDerbyDriverInstance() {
try {
Class.forName(DRIVER).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
Logger.getLogger(DerbyTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static boolean tableAlreadyExists(SQLException e) {
return e.getSQLState().equals("X0Y32");
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
initDerbyHomeAndDriver();
getConnection(true);
shutdownConnectionAndCleanup();
} catch (SQLException ex) {
Logger.getLogger(DerbyTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
我也试过使用外部库来删除文件夹,比如apache的org.apache.commons.io.FileDeleteStrategy.FORCE.delete(file);
或import org.apache.commons.io.FileUtils.deleteDirectory(file);
,看起来derby系统在数据库关闭后仍然挂起文件。
预期行为:退出时删除system directory。
编辑:
Windows进程资源管理器显示,在关闭数据库连接后,derby.log仍处于打开状态:
2条答案
按热度按时间bvk5enib1#
假设是Derby代码本身无法关闭这个文件,我认为这是一个bug。
关闭Engine之后,Derby显然应该关闭它的日志并释放对它的所有引用。
如果您可以访问https://www.eclipse.org/mat/之类的工具,您可能能够找到哪个线程(甚至是哪个堆栈帧?)分配了对derby.log的引用,但未能释放它。
如果您可以将此行为封装在一个小型测试程序中进行演示,我建议您针对Derby(http://db.apache.org/derby/DerbyBugGuidelines.html)记录一个bug,以便开发人员可以自己重现它并找出如何修复它。
同时,您可以通过禁用derby.log文件或将derby.log文件重新定位到另一个目录来解决这个问题。
这显然不是一个修复,但它可能是一个行为上的改进,这样这个缺陷就不会再阻碍你的工作了。下面是一些关于如何控制derby.log文件的文档:https://builds.apache.org/job/Derby-docs/lastSuccessfulBuild/artifact/trunk/out/devguide/cdevdvlp25889.html
0wi1tuuw2#
当前使用的URL:
只是关闭数据库连接,而不是Derby本身,这就是为什么Derby仍然锁定derby.log文件的原因。要关闭Derby,需要使用以下URL:
更多详情请访问Derby网站:https://db.apache.org/derby/docs/10.16/devguide/tdevdvlp20349.html