java - 在 Java 中完全卸载 JDBC 驱动程序

标签 java mybatis sqlanywhere

我有一个使用 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 升级终止我的应用程序。

我还能做些什么来确保删除所有驱动程序引用吗?还是有更好的方法来解决这个问题?

最佳答案

大多数 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());

关于java - 在 Java 中完全卸载 JDBC 驱动程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58140908/

相关文章:

java - java 中的 Math.pow()

Java:按位异或运算符如何评估条件? (^)

java - 如何将 ascii 值字符串转换回其字符串/字符值?

java - ORM 和对象映射之间的区别?

SqlAnywhere 的 Node.js 驱动程序 - 超出准备语句

java - wait() 不强制线程等待?

java - MyBatis:Sybase 存储过程返回零行

java - MyBatis 正在寻找 org/hsqldb/DatabaseURL,而我设置为 MmySQL

vb.net - Windows 服务未连接到 SQL Anywhere 数据库

mysql - 如何在Sybase SQL Anywhere 中模拟MySQL 的bit_count 函数?