すぱいだー日記。

2008.03.07(Fri)

Class.forName で DB アクセスできるようになる理由

Java研修DB(だいたいMDBかな) にアクセスするプログラムを作ることになったとき、講師はほぼ 100% 「JDBC Driver を使用するためには Class.forName を使用します」と言うはず。ただ、呪文のごとく。

で、Class.forName の API を見てみる。

forName(String name, boolean initialize, ClassLoader loader)

指定されたクラスローダを使って、指定された文字列名を持つクラスまたはインタフェースに関連付けられた Class オブジェクトを返します

そして疑問が生まれる。「クラスをロードするだけでなんでDBアクセスできるようになるの?」と。

講師はなぜできるかは説明しない。分かってないってことは無いと思うけど「まだ初心者だから覚えとけばいい」的な感じだろう。

けど、ここは言わせてもらう!

説明すべきだ!

おかげで今になってようやく理解できた。特に必要なかったのもあるけど、ふと気になって調べてみた。

んで、こういう事(間違ってたら恥ずかしいから早く教えてください)。

ベンダJDBC Driver は java.sql.Driver を実装している必要があり、その実装クラスは static initializer で java.sql.DriverManager.registerDriver(java.sql.Driver) を使って登録している。

Class.forName -> static initializer -> DriverManager.registerDriver って流れ。あとは DriverManager を経由して各 Driver にアクセスして使用する。

ついでにいくつかの JDBC Driver のソースを確認してみた。

sun

JDBC Driver の登録

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

static initializer

public class JdbcOdbcDriver
	extends		JdbcOdbcObject
	implements	JdbcOdbcDriverInterface
{
  //--------------------------------------------------------------------
  // Static method to be executed when the class is loaded.
  //--------------------------------------------------------------------
  static
  {		
    JdbcOdbcTracer tracer1 = new JdbcOdbcTracer();
    if (tracer1.isTracing ()) {
      tracer1.trace ("JdbcOdbcDriver class loaded");
    }

    JdbcOdbcDriver driver = new JdbcOdbcDriver ();

    // Attempt to register the driver

    try {
      DriverManager.registerDriver (driver);
    }
    catch (SQLException ex) {
      if (tracer1.isTracing ()) {
        tracer1.trace ("Unable to register driver");
      }  
    }
  }

MySQL

JDBC Driver の登録

Class.forName("com.mysql.jdbc.Driver");

static initializer

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
  // ~ Static fields/initializers
  // ---------------------------------------------

  //
  // Register ourselves with the DriverManager
  //
  static {
    try {
      java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
      throw new RuntimeException("Can't register driver!");
    }
  }

PostgreSQL

JDBC Driver の登録

Class.forName("org.postgresql.Driver"); 

static initializer

public class Driver implements java.sql.Driver
{

    // make these public so they can be used in setLogLevel below

    public static final int DEBUG = 2;
    public static final int INFO = 1;

    private static final Logger logger = new Logger();
    private static boolean logLevelSet = false;

    static
    {
        try
        {
            // moved the registerDriver from the constructor to here
            // because some clients call the driver themselves (I know, as
            // my early jdbc work did - and that was based on other examples).
            // Placing it here, means that the driver is registered once only.
            java.sql.DriverManager.registerDriver(new Driver());
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
    }

SQLite

JDBC Driver の登録

Class.forName("org.sqlite.JDBC");

static initializer

public class JDBC implements Driver
{
    private static final String PREFIX = "jdbc:sqlite:";

    static {
        try {
            DriverManager.registerDriver(new JDBC());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

長年の疑問がまた一つ解けたよ。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証