JDBC を使用して MySQL を操作するための簡単な分析では、Class.forName("com.mysql.jdbc.Driver") を追加する必要があります。

JDBC を使用して MySQL を操作するための簡単な分析では、Class.forName("com.mysql.jdbc.Driver") を追加する必要があります。

導入

データベースに接続するためにJDBCを使用することに慣れている場合は、データベースに接続するためのコードはClass.forNameに基づいている必要があることを知っている必要があります。

("com.mysql.jdbc.Driver");
  パブリック静的Connection getConnection() はClassNotFoundException、SQLExceptionをスローします {
    if (接続 == null) {
      クラス.forName("com.mysql.jdbc.Driver");
      接続 = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
    }
    接続を返します。
  }

これまで、なぜこのようなステートメントが必要なのか考えたことはありませんでした。ドキュメントに従って実行するだけです。この記事では、そうする理由を説明してみたいと思います。

クラスローディングメカニズム

その前に、Java のクラスロードメカニズムについて説明しましょう。

Java では、クラスを使用する場合は、そのクラスが JVM にロードされている必要があります。ロード プロセスは、実際には、クラスの完全修飾名を通じてクラスを定義するバイナリ バイト ストリームを取得し、バイト ストリームによって表される静的ストレージ構造をメソッドの動的ランタイム データ構造に変換することです。同時に、メソッド領域内のこのクラスのデータ アクセス エントリとして、java.lang.Class オブジェクトがメモリ内にインスタンス化されます (ここでの使用のため)。

次のような状況では、クラスのロードがトリガーされる可能性があります (<<Java 仮想マシンの詳細な理解>> から引用)。

1. 4 つのバイトコード命令 new、getstatic、putstatic、または invokestatic に遭遇したときに、クラスが初期化されていない場合は、まずその初期化をトリガーする必要があります。これら 4 つの命令を生成する最も一般的な Java コード シナリオは、new キーワードを使用してオブジェクトをインスタンス化する場合、クラスの静的フィールドを読み取ったり設定する場合 (final によって変更され、コンパイル時に結果が定数プールに配置される静的フィールドを除く)、およびクラスの静的メソッドを呼び出す場合です。

2. java.lang.reflect パッケージのメソッドを使用してクラスをリフレクションで呼び出す場合、クラスが初期化されていない場合は、まずその初期化をトリガーする必要があります。

3. クラスを初期化するときに、その親クラスが初期化されていないことが判明した場合は、まずその親クラスの初期化をトリガーする必要があります。

4. 仮想マシンが起動すると、ユーザーは実行するメイン クラス (main() メソッドを含むクラス) を指定する必要があり、仮想マシンは最初にこのメイン クラスを初期化します。

クラス.forName

公式 Java ドキュメントでは、Class.forName は実行時にクラスを動的にロードし、戻り値は生成された Class オブジェクトであると説明されています。

そうすると、jdbc でClass.forName("com.mysql.jdbc.Driver");を使用すると、com.mysql.jdbc.Driver クラスが JVM にロードされるだけであることは明らかであり、ほとんどの人はこの理由を知っているはずです。

しかし、Class.forName はクラスをロードするだけであり、返された Class オブジェクトに対して何の操作も行わないことを知っておく必要があります。では、なぜ後でそれを直接使用できるのでしょうか。

まず、Class.forName はネイティブ メソッド forName0(...); を呼び出します。

@発信者センシティブ
パブリック スタティック クラス <?> forName(String className)
      ClassNotFoundException をスローします {
  クラス<?> 呼び出し元 = Reflection.getCallerClass();
  forName0(className, true, ClassLoader.getClassLoader(caller), caller) を返します。
}

プライベート静的ネイティブ Class<?> forName0(String name、boolean initialize、ClassLoader loader、Class<?> caller);

forName0 には、クラスのロード後に初期化を実行するかどうかを示すために使用される boolean initialize というキー パラメーターがあることに注意してください。コード内で true の場合、初期化操作が実行されることを意味することがわかります。

初期化プロセスは、実際には変数に値を割り当てるプロセスです(初期値を割り当てたり、コンストラクターを呼び出したりすることはありません)。親クラスの初期化を含む、すべてのクラス変数の割り当てと静的コード ステートメント ブロックの実行コードが含まれます。

com.mysql.jdbc.Driver ドライバー クラスを確認します。

パブリッククラスDriverはNonRegisteringDriverを拡張し、java.sql.Driverを実装します。
  パブリックDriver()はSQLExceptionをスローします{
  }

  静的{
    試す {
      DriverManager.registerDriver(新しいDriver());
    } キャッチ (SQLException var1) {
      throw new RuntimeException("ドライバーを登録できません!");
    }
  }
}

このクラスには静的コード ブロックが定義されています。静的コード ブロック内にドライバー クラスのインスタンスが作成され、DriverManager に登録されます。静的コード ブロックの内容は初期化プロセス中に実行されるため、 DriverManager.getConnectionを通じて直接接続を取得できます。

その他のロードクラスメソッド

理解しておく必要があるのは、Java では、クラスを明示的にロードできるのは Class.forName() だけではないということです。では、Class.forName() の代わりに他の読み込みメソッドを使用しないのはなぜでしょうか?

ClassLoader.getSystemClassLoader().loadClass()

クラスは、クラス ローダーを介して JVM にロードすることもできます。ドライバー クラスはClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");

しかし、loadClass の実装を詳しく見てみると、

パブリック Class<?> loadClass(String name) は ClassNotFoundException をスローします {
  loadClass(name, false) を返します。
}

保護された Class<?> loadClass(String name, boolean resolve);

オーバーロードされたメソッドが呼び出され、そのメソッドにもブール変数 boolean resolve があり、呼び出されるとデフォルトで false に設定されることがわかります。このパラメータは、ロードされたクラスをリンクするかどうかを識別するために使用されます。リンクしない場合は、初期化操作は行われません。

したがって、このクラスロード方法を使用すると、理論的にはドライバークラスは使用できません。

新しいキーワード

また、new キーワードを使用して読み込み操作を実行することもできます。new キーワードを使用すると、クラスが読み込まれているかどうかがチェックされます。読み込まれていない場合は、クラスが読み込まれます。したがって、クラスでは次のように記述することもできます。

パブリック静的Connection getConnection() はClassNotFoundException、SQLExceptionをスローします {
  if (接続 == null) {
    new Driver(); //静的コード ブロックは自動的に呼び出されます connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxx");
  }
  接続を返します。
}

しかし実際には、ドライバー クラスの静的コード ブロック内に、オブジェクトをインスタンス化して DriverMananger に登録する操作がすでに存在します。したがって、ここではオブジェクトをインスタンス化するプロセスはまったくありません。最適化プロセスとみなせる Class.forName を使用するだけです。

Class.forName("com.mysql.jdbc.Driver")を使用する必要はありません。

テスト中に、 Class.forName("com.mysql.jdbc.Driver")明示的に使用しなくてもデータベースに接続できることがわかり、非常に奇妙だと感じました。

コードを詳細に追跡した結果、MySQL ドライバー パッケージを導入すると、使用時にドライバー パッケージで提供される構成ファイルに従って、デフォルトでクラスが作成されることがわかりました。

したがって、実際には、ドライバー パッケージが導入されている限り、jdbc を使用して DriverManage を介して直接接続を取得できます。

パブリック静的接続getConnection() SQLException {
  DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx"); を返します。
}

要約する

上記は、JDBC を使用して MySQL を操作するときに Class.forName("com.mysql.jdbc.Driver") を追加する必要がある理由についての紹介です。お役に立てれば幸いです。ご質問がある場合は、メッセージを残してください。すぐに返信いたします。また、123WORDPRESS.COM ウェブサイトをサポートしてくださっている皆様にも感謝申し上げます。

以下もご興味があるかもしれません:
  • データベース接続のURLの詳細な説明と概要
  • MySql リンク URL パラメータの設定について
  • MySQLのdriverClassNameとurlの使い方

<<:  Vueフロントエンドの効率的な開発のためのレンダリング手順をリストします

>>:  Windows に Docker をインストールする詳細なチュートリアル

推薦する

MySQL における ESCAPE キーワードの使用法の詳細な説明

MySQL エスケープエスケープとは、エスケープ文字の本来の意味を意味します。エスケープ文字の目的は...

MySQLで重複行を削除する方法

SQL文 /* MySQL で重複行を削除するいくつかの方法 ---Chu Minfei ---20...

MySQL 全文あいまい検索 MATCH AGAINST メソッドの例

MySQL 4.x 以降では、全文検索 MATCH ... AGAINST モード (大文字と小文字...

ソースコード分析からTomcatがサーブレットの初期化を呼び出す方法の詳細な説明

目次導入1. Tomcatを起動するコード2. Tomcatフレームワーク3. コンテナを作成する ...

CentOS 6.4 MySQL 5.7.18 のインストールと設定方法のグラフィックチュートリアル

Centos6.4 で mysql5.7.18 をインストールするための具体的な手順が全員に共有され...

MySQLの自己接続と結合の詳細な理解

1. MySQL 自己接続MySQL では、情報を照会するときに自分自身に接続 (自己接続) する必...

HTML テーブル マークアップ チュートリアル (16): タイトルの水平方向の配置属性 ALIGN

デフォルトでは、表のタイトルは水平方向に中央揃えされます。ALIGN 属性を使用して、タイトル テキ...

Vueオプションの詳細な説明

目次1. オプションとは何ですか? 2. 含まれる属性3. エントリー属性エルデータ方法コンポーネン...

ウェブサイトのユーザビリティを向上させる10のヒント

企業の Web サイト、個人のブログ、ショッピング Web サイト、ゲーム Web サイトなど、どの...

Windows Server 2008 のサーバー パフォーマンス監視に関するチュートリアル

次に、ログ管理、ログのアーカイブ、ログのトラブルシューティング、イベントの転送と収集のためのコンピュ...

ES6 ループと反復可能オブジェクトの例

この記事では、ES6 の for ... of ループについて説明します。古い方法以前は、JavaS...

初心者がHTMLタグを学ぶ(1)

初心者は、いくつかの HTML タグを理解することで HTML を学習できます。この入門書は、初心者...

HTMLエリアタグの詳しい説明

<area> タグは、イメージ マップ内の領域を定義します (注: イメージ マップはク...

既存のDockerコンテナの内容を変更する方法

1. Docker psはコンテナをリストします 2. Docker cpはコンテナにファイルをコピ...

MySql ストアド プロシージャ パラメータの初歩的な使用法の詳細な説明

パラメータでのストアドプロシージャの使用IN パラメータは、プロシージャに情報を渡すためにのみ使用さ...