用Java完全卸载JDBC驱动程序

问题描述 投票:2回答:1

我有一个使用Java,mybatis和SQL Anywhere的应用程序。由于某些情况,我必须在运行时手动加载SQLA驱动程序jar。我使用此代码进行此操作:

    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升级终止了我的应用程序。

还有其他我可以做的事情以确保删除所有驱动程序引用吗?还是有更好的方法来解决这个问题?

java mybatis sqlanywhere
1个回答
0
投票

[大多数JDBC驱动程序会自动自行注册,例如您以前只需要调用Class.forName()来加载驱动程序类,然后它将自动注册它。

如今,您甚至不必再这样做,因为它们使用服务框架通过仅在类路径上进行自动注册,但是由于您的JDBC jar文件不在类路径上,因此此处不再适用。

由于还注册了驱动程序,因此它被注册了两次,注销时,只删除您创建的注册,而不是自动注册的注册。

要删除自动注册的实例,您必须枚举所有已注册的驱动程序以找到要注销的实例:

// 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());
© www.soinside.com 2019 - 2024. All rights reserved.