【问题标题】:How to use a JDBC driver from an arbitrary location如何从任意位置使用 JDBC 驱动程序
【发布时间】:2010-09-22 06:37:11
【问题描述】:

我需要测试与数据库的 JDBC 连接。执行此操作的 java 代码应该很简单:

DriverManager.getConnection("jdbc connection URL", "username", "password");

驱动程序管理器将为给定的连接 URL 查找适当的驱动程序。但是我需要能够在运行时加载 JDBC 驱动程序(jar)。即我在运行上述代码的 sn-p 的 java 应用程序的类路径上没有 JDBC 驱动程序。

所以我可以使用此代码加载驱动程序,例如:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"jar URL"}, this.getClass().getClassLoader());
Driver driver = (Driver) Class.forName("jdbc driver class name", true, classLoader).newInstance();

但是驱动管理器仍然不会接收它,因为我无法告诉它使用哪个类加载器。我试过设置当前线程的上下文类加载器,还是不行。

有人知道实现这一目标的最佳方法吗?

【问题讨论】:

  • 类路径中没有驱动程序是否有充分的理由?
  • 是的。该应用程序可以连接到许多数据库。此外,出于许可原因,我不能捆绑所有驱动程序。我想要实现的是一个简单的对话框,让用户在应用程序运行时加载 jar。
  • 我又像服务器端开发人员一样思考...... :)

标签: java jdbc driver


【解决方案1】:

来自Pick your JDBC driver at runtime的文章;我只是将代码发布在这里以供参考。

这个想法是让驱动程序管理器认为驱动程序是从系统类加载器加载的。为此,我们使用这个类:

public class DelegatingDriver implements Driver
{
    private final Driver driver;

    public DelegatingDriver(Driver driver)
    {
        if (driver == null)
        {
            throw new IllegalArgumentException("Driver must not be null.");
        }
        this.driver = driver;
    }

    public Connection connect(String url, Properties info) throws SQLException
    {
       return driver.connect(url, info);
    }

    public boolean acceptsURL(String url) throws SQLException
    {
       return driver.acceptsURL(url);
    }

    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
    {
        return driver.getPropertyInfo(url, info);
    }

    public int getMajorVersion()
    {
        return driver.getMajorVersion();
    }

    public int getMinorVersion()
    {
        return driver.getMinorVersion();
    }

    public boolean jdbcCompliant()
    { 
        return driver.jdbcCompliant();
    }
}

这样,您注册的驱动程序的类型为DelegatingDriver,它与系统类加载器一起加载。您现在只需使用您想要的任何类加载器加载您真正想要使用的驱动程序。例如:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"path to my jdbc driver jar"}, this.getClass().getClassLoader());
Driver driver = (Driver) Class.forName("org.postgresql.Driver", true, classLoader).newInstance();
DriverManager.registerDriver(new DelegatingDriver(driver)); // register using the Delegating Driver

DriverManager.getDriver("jdbc:postgresql://host/db"); // checks that the driver is found

【讨论】:

    【解决方案2】:

    问题是DriverManager 执行“使用直接调用者的类加载器实例的任务”。请参阅Secure Coding Guidelines for the Java Programming Language, version 2.0 的指南 6-3。在这种情况下,系统类加载器并没有什么特别之处。

    只是为了好玩,不久前我写了一篇关于这个主题的博客文章(编辑:现已失效)。我的解决方案虽然比Nick Sayer's solution 更复杂,但更完整,甚至可以使用不受信任的代码(编辑:不推荐使用不受信任代码的概念,以便在 Java 17 中删除)。另请注意URLClassLoader.newInstance 优于new URLClassLoader

    【讨论】:

      猜你喜欢
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多