19

データベースへの JDBC 接続をテストする必要があります。これを行うための Java コードは、次のように単純にする必要があります。

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

ドライバー マネージャーは、指定された接続 URL に適したドライバーを検索します。ただし、実行時に JDBC ドライバー (jar) をロードできる必要があります。つまり、上記のコード スニペットを実行する 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();

しかし、どのクラスローダーを使用するかを伝えることができないため、ドライバーマネージャーはまだそれを取得しません。現在のスレッドのコンテキスト クラスローダーを設定しようとしましたが、まだ機能しません。

誰でもそれを達成するための最良の方法について何か考えがありますか?

4

2 に答える 2

20

記事から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
于 2008-11-14T01:06:37.660 に答える
5

問題はDriverManager、「即時呼び出し元のクラス ローダー インスタンスを使用するタスク」を実行することです。Java プログラミング言語バージョン 2.0のセキュア コーディング ガイドラインのガイドライン 6-3 を参照してください。この場合、システム クラス ローダーは決して特別なものではありません。

念のため、私はしばらく前にこのテーマに関するブログ エントリ (編集: 現在は廃止されています) を書きました。私のソリューションは、 Nick Sayer のソリューションよりも複雑ですが、より完全であり、信頼されていないコードからも機能します (編集: 信頼されていないコードの概念は、Java 17 での削除のために非推奨になっています)。また、メモURLClassLoader.newInstanceよりも優先されnew URLClassLoaderます。

于 2008-11-14T11:33:05.480 に答える