我有一个使用 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/