【问题标题】:Unable to delete Derby System Directory for Embedded Database无法删除嵌入式数据库的 Derby 系统目录
【发布时间】:2018-05-14 22:26:25
【问题描述】:

在为 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 在数据库连接关闭后仍处于打开状态:

【问题讨论】:

  • Windows?哪些文件无法删除?
  • 编辑了注释以指定这是在 Windows 计算机上。原始帖子指出我无法删除的文件是 Derby 的系统目录 (db.apache.org/derby/docs/10.3/tuning/rtunproper32066.html)。不过,退出程序后,我可以删除该文件夹。
  • 尝试使用 Microsoft Process Explorer 工具检查您正在运行的程序,并查看它打开了哪些文件和目录。这些文件中至少有一个是 Derby 系统目录中的文件。但是哪一个?你能用你的发现更新你的问题吗? docs.microsoft.com/en-us/sysinternals/downloads/… 当然,请确保在执行“shutdown=true”之后检查您的程序。
  • @BryanPendleton 看起来 Derby 正在挂在 derby.log 上。见编辑。

标签: java derby embedded-database


【解决方案1】:

假设是 Derby 代码本身未能关闭此文件,这对我来说似乎是一个错误。

关闭引擎后,Derby 显然应该关闭它的日志并释放所有对它的引用。

如果您可以访问诸如 https://www.eclipse.org/mat/ 之类的工具,您可能能够找到哪个线程(甚至哪个堆栈框架?)已将此引用分配给 derby.log 并且未能释放它。

如果您可以将此行为封装在一个演示它的小型测试程序中,我鼓励您针对 Derby (http://db.apache.org/derby/DerbyBugGuidelines.html) 记录一个错误,以便开发人员可以自己重现它并找出解决方法。

与此同时,您可以通过禁用 derby.log 文件或将 derby.log 文件重新定位到另一个目录来解决此问题。

这显然不是一个修复,但它可能是对行为的改进,这样这个缺陷就不会再阻碍你的工作了?下面是一些关于如何控制 derby.log 文件的文档:https://builds.apache.org/job/Derby-docs/lastSuccessfulBuild/artifact/trunk/out/devguide/cdevdvlp25889.html

【讨论】:

    猜你喜欢
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    相关资源
    最近更新 更多