Полная выгрузка драйвера JDBC в Java - PullRequest
2 голосов
/ 27 сентября 2019

У меня есть приложение, которое использует Java, mybatis и SQL Anywhere.Из-за некоторых обстоятельств я должен вручную загрузить JAR-файл драйвера SQLA во время выполнения.Я получил это работая с этим кодом:

    public static URLClassLoader ucl;
    public static Driver saDriver;


    public static final void loadSqlAnywhere(SqlAnywhereVersions version)
    {
        if (saDriver == null)
        {
            try
            {
                File jarPath = "path\\to\\sajdbc4.jar";
                URL jarUrl = new URL("jar:file:" + jarPath.getAbsolutePath() + "!/");

                String driverClass = "sap.jdbc4.sqlanywhere.IDriver";

                ucl = URLClassLoader.newInstance(new URL[]{ jarUrl });
                saDriver = new DriverShim((Driver) Class.forName(driverClass, true, ucl).newInstance());
                DriverManager.registerDriver(saDriver);

            }
            catch (Exception ex)
            {
                // Could not load SQL Anywhere driver
            }
        }
    }

Во время работы приложения возможно обновление SQL Anywhere.Итак, мне нужно полностью выгрузить старый драйвер, позволить обновлению произойти, а затем инициализировать с последним jar.Я попробовал это:

    private static List<SqlSession> sessions = new ArrayList<>();
    private static SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder();
    public static final void unloadSqlAnywhere()
    {
        if (saDriver != null)
        {

            // Close out any existing sessions
            for (SqlSession session : sessions)
            {
                session.close();
            }
            sessions.clear();

             // Kill the session factory
            sessionFactory = null;

            try
            {
                DriverManager.deregisterDriver(saDriver);
                saDriver = null;

                ucl.close();
                ucl = null;
            }
            catch (Exception ex)
            {
                // Failed to unregister SQL Anywhere driver
            }
        }
    }

Но с помощью jprofiler я вижу, что DriverManager все еще ссылается на sap.jdbc4.sqlanywhere.IDriver, что приводит к тому, что обновление SQL Anywhere убивает мое приложение.

Есть ли что-тобольше я могу сделать, чтобы убедиться, что все ссылки на драйверы удалены?Или есть лучший способ сделать это?

1 Ответ

0 голосов
/ 28 сентября 2019

Большинство драйверов JDBC автоматически регистрируются, например, раньше вы просто вызывали Class.forName() для загрузки класса драйвера, и это автоматически регистрировало бы его.

В настоящее время вам даже не нужноделайте это больше, так как они используют сервисную среду для автоматической регистрации, просто находясь в пути к классам, но поскольку ваш файл jar JDBC не находится в пути к классам, это здесь не применимо.

Поскольку вы также регистрируетесьдрайвер, он регистрируется дважды, и когда вы отменяете регистрацию, вы удаляете только созданную вами регистрацию, а не ту, которая была автоматически зарегистрирована.

Чтобы удалить автоматически зарегистрированный экземпляр, необходимо перечислить все зарегистрированныедрайверы для поиска экземпляра для отмены регистрации:

// Any Java version
for (Enumeration<Driver> e = DriverManager.getDrivers(); e.hasMoreElements(); ) {
    Driver driver = e.nextElement();
    if (driver.getClass().getName().equals("sap.jdbc4.sqlanywhere.IDriver"))
        DriverManager.deregisterDriver(driver);
}
// Java 9+
Optional<Driver> driver = DriverManager.drivers()
        .filter(d -> d.getClass().getName().equals("sap.jdbc4.sqlanywhere.IDriver"))
        .findAny();
if (driver.isPresent())
    DriverManager.deregisterDriver(driver.get());
...