Eine kurze Analyse der Verwendung von JDBC zum Betreiben von MySQL erfordert das Hinzufügen von Class.forName("com.mysql.jdbc.Driver")

Eine kurze Analyse der Verwendung von JDBC zum Betreiben von MySQL erfordert das Hinzufügen von Class.forName("com.mysql.jdbc.Driver")

Einführung

Wenn Sie mit der Verwendung von JDBC zum Herstellen einer Verbindung zur Datenbank vertraut sind, müssen Sie wissen, dass der Code zum Herstellen einer Verbindung zur Datenbank auf Class.forName basieren muss

("com.mysql.jdbc.Driver");
  öffentliche statische Verbindung getConnection() löst ClassNotFoundException, SQLException { aus.
    wenn (Verbindung == null) {
      Klasse.fürName("com.mysql.jdbc.Driver");
      Verbindung = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
    }
    Rückverbindung;
  }

Ich habe noch nie darüber nachgedacht, warum eine solche Anweisung erforderlich ist. Ich mache es einfach gemäß der Dokumentation. In diesem Artikel werde ich versuchen, den Grund dafür zu erklären.

Mechanismus zum Laden von Klassen

Lassen Sie uns vorher über den Klassenlademechanismus in Java sprechen.

Wenn Sie in Java eine Klasse verwenden möchten, müssen Sie verlangen, dass die Klasse in die JVM geladen wurde. Der Ladevorgang besteht eigentlich darin, den binären Bytestream abzurufen, der die Klasse über den vollqualifizierten Namen der Klasse definiert, und dann die durch den Bytestream dargestellte statische Speicherstruktur in die dynamische Laufzeitdatenstruktur der Methode zu konvertieren. Gleichzeitig wird im Speicher ein java.lang.Class-Objekt als Datenzugriffseintrag für diese Klasse im Methodenbereich instanziiert (für unsere Verwendung).

Die folgenden Situationen können das Laden von Klassen auslösen (Zitat aus <<Detailliertes Verständnis der Java Virtual Machine>>):

1. Wenn Sie auf die vier Bytecode-Anweisungen „new“, „getstatic“, „putstatic“ oder „invokestatic“ stoßen und die Klasse noch nicht initialisiert wurde, müssen Sie zuerst ihre Initialisierung auslösen. Diese vier Anweisungen werden in den folgenden Java-Codes am häufigsten generiert: beim Instanziieren eines Objekts mit dem Schlüsselwort „new“, beim Lesen oder Festlegen eines statischen Felds einer Klasse (mit Ausnahme von statischen Feldern, die durch final geändert werden und deren Ergebnisse zur Kompilierzeit in den Konstantenpool gestellt werden) und beim Aufrufen einer statischen Methode einer Klasse.

2. Wenn Sie die Methoden des Pakets java.lang.reflect verwenden, um eine Klasse reflektierend aufzurufen, müssen Sie zuerst die Initialisierung der Klasse auslösen, falls diese noch nicht initialisiert wurde.

3. Wenn beim Initialisieren einer Klasse festgestellt wird, dass ihre übergeordnete Klasse nicht initialisiert wurde, müssen Sie zuerst die Initialisierung der übergeordneten Klasse auslösen.

4. Wenn die virtuelle Maschine gestartet wird, muss der Benutzer eine auszuführende Hauptklasse angeben (die Klasse, die die main()-Methode enthält), und die virtuelle Maschine initialisiert zuerst diese Hauptklasse.

Klasse.fürName

Die offizielle Java-Dokumentation erklärt Class.forName als dynamisches Laden einer Klasse zur Laufzeit, und der Rückgabewert ist das generierte Class-Objekt.

Dann ist es offensichtlich, dass die Verwendung Class.forName("com.mysql.jdbc.Driver"); in jdbc einfach die Klasse com.mysql.jdbc.Driver in die JVM lädt, und die meisten Leute sollten diesen Grund kennen.

Wir müssen jedoch wissen, dass Class.forName anscheinend nur die Klasse lädt und wir nicht einmal irgendwelche Operationen am zurückgegebenen Class-Objekt durchführen. Warum können wir es also später direkt verwenden?

Zuerst ruft Class.forName die native Methode forName0(...) auf.

@AnruferSensitiv
öffentliche statische Klasse<?> fürName(String className)
      wirft ClassNotFoundException {
  Klasse<?> Anrufer = Reflection.getCallerClass();
  returniere forName0(Klassenname, true, ClassLoader.getClassLoader(Anrufer), Anrufer);
}

private statische native Klasse<?> fürName0(String-Name, Boolesche Initialisierung,ClassLoader-Loader,Class<?>-Aufrufer);

Es ist zu beachten, dass es in forName0 einen Schlüsselparameter gibt, boolean initialize, der angibt, ob nach dem Laden der Klasse eine Initialisierung durchgeführt werden soll. Sie können sehen, dass, wenn es im Code wahr ist, dies bedeutet, dass der Initialisierungsvorgang ausgeführt wird.

Der Initialisierungsprozess ist eigentlich der Prozess der Zuweisung von Werten zu Variablen (keine Zuweisung von Anfangswerten und kein Aufrufen des Konstruktors). Enthält die Zuweisung aller Klassenvariablen und den Ausführungscode von statischen Code-Anweisungsblöcken, einschließlich der Initialisierung der übergeordneten Klasse.

Sehen Sie sich die Treiberklasse com.mysql.jdbc.Driver an:

öffentliche Klasse Driver erweitert NonRegisteringDriver implementiert java.sql.Driver {
  öffentlicher Treiber() wirft SQLException {
  }

  statisch {
    versuchen {
      DriverManager.registerDriver(neuer Treiber());
    } Fang (SQLException var1) {
      throw new RuntimeException("Treiber kann nicht registriert werden!");
    }
  }
}

In dieser Klasse wird ein statischer Codeblock definiert. Eine Treiberklasseninstanz wird im statischen Codeblock erstellt und bei DriverManager registriert. Der Inhalt des statischen Codeblocks wird während des Initialisierungsprozesses ausgeführt, sodass eine Verbindung direkt über DriverManager.getConnection hergestellt werden kann.

Andere Ladeklassenmethoden

Wir müssen verstehen, dass in Java Klassen nicht nur über Class.forName() explizit geladen werden können. Warum also nicht anstelle von Class.forName() andere Lademethoden verwenden?

ClassLoader.getSystemClassLoader().loadClass()

Eine Klasse kann auch über einen Klassenlader in die JVM geladen werden. Die Treiberklasse kann auch über ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");

Aber wenn wir uns die Implementierung von loadClass genauer ansehen:

öffentliche Klasse<?> loadClass(String name) löst ClassNotFoundException { aus
  gibt loadClass(Name, false) zurück;
}

geschützte Klasse<?> loadClass(Stringname, Boolesche Auflösung);

Sie können sehen, dass es eine überladene Methode aufruft, die auch eine boolesche Variable „Boolean Resolve“ hat, die beim Aufruf standardmäßig auf „False“ gesetzt ist. Dieser Parameter wird verwendet, um anzugeben, ob die geladene Klasse verknüpft werden soll. Wenn nicht, erfolgt kein Initialisierungsvorgang.

Wenn diese Methode zum Laden von Klassen verwendet wird, kann die Treiberklasse daher theoretisch nicht verwendet werden.

neues Schlüsselwort

Sie können das Schlüsselwort new auch zum Ausführen von Ladevorgängen verwenden. Wenn Sie das Schlüsselwort new verwenden, wird geprüft, ob die Klasse geladen wurde. Wenn sie nicht geladen wurde, wird sie geladen. Wir können dies also auch in unsere Klasse schreiben:

öffentliche statische Verbindung getConnection() löst ClassNotFoundException, SQLException { aus.
  wenn (Verbindung == null) {
    neuer Treiber(); //Der statische Codeblock wird automatisch aufgerufen connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxx");
  }
  Rückverbindung;
}

Tatsächlich gibt es jedoch bereits eine Operation zum Instanziieren des Objekts und zur Registrierung bei DriverManager im statischen Codeblock der Treiberklasse. Es gibt hier also überhaupt keinen Prozess der Instanziierung eines Objekts. Verwenden Sie einfach Class.forName, was als Optimierungsprozess angesehen werden kann.

Sie müssen Class.forName("com.mysql.jdbc.Driver") nicht verwenden.

Während des Tests stellte ich fest, dass ich eine Verbindung zur Datenbank herstellen konnte, auch wenn ich Class.forName("com.mysql.jdbc.Driver") nicht explizit verwendete, was ich sehr seltsam fand.

Nachdem wir den Code eingehend verfolgt hatten, stellten wir fest, dass, solange wir das MySQL-Treiberpaket einführen, bei Verwendung standardmäßig eine Klasse gemäß der unter dem Treiberpaket bereitgestellten Konfigurationsdatei erstellt wird.

Solange das Treiberpaket eingeführt ist, können Sie also tatsächlich jdbc verwenden, um die Verbindung direkt über DriverManage herzustellen.

öffentliche statische Verbindung getConnection() SQLException {
  return DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
}

Zusammenfassen

Das Obige ist meine Einführung, warum Sie Class.forName("com.mysql.jdbc.Driver") hinzufügen müssen, wenn Sie JDBC zum Betreiben von MySQL verwenden. Ich hoffe, es wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und ich werde Ihnen rechtzeitig antworten. Ich möchte auch allen für ihre Unterstützung der Website 123WORDPRESS.COM danken!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung und Zusammenfassung der URL zur Datenbankverbindung
  • Über die Einstellung der MySql-Link-URL-Parameter
  • So verwenden Sie den MySQL-Treiberklassennamen und die URL

<<:  Listen Sie Rendering-Anweisungen für eine effiziente Entwicklung des Vue-Frontends auf

>>:  Detailliertes Tutorial zur Installation von Docker unter Windows

Artikel empfehlen

Eine "klassische" Falle der MySQL UPDATE-Anweisung

Inhaltsverzeichnis 1. Problematische SQL-Anweisun...

Detaillierte Interpretation der Datei /etc/fstab im Linux-System

Vorwort [root@localhost ~]# cat /etc/fstab # # /e...

Lernen Sie die Grundlagen von nginx

Inhaltsverzeichnis 1. Was ist nginx? 2. Was kann ...

Das WeChat-Applet implementiert das Schlangenspiel

In diesem Artikel wird der spezifische Code des W...

So fügen Sie der Seite über Element UI eine Seitennavigationsleiste hinzu

brauchen Fügen Sie eine Paging-Leiste hinzu, die ...

Häufig verwendete HTML-Format-Tags_Powernode Java Academy

1. Titel HTML definiert sechs <h>-Tags: <...

So unterstützen Sie vollständiges Unicode in MySQL/MariaDB

Inhaltsverzeichnis Einführung in utf8mb4 Fehler b...

MySQL-Datenbank Shell import_table Datenimport

Inhaltsverzeichnis MySQL Shell import_table Daten...

Grafisches Tutorial zur Installation und Konfiguration von MySQL 5.7.11 Zip

1. Laden Sie das MySQL 5.7.11 Zip-Installationspa...

So öffnen Sie das MySQL-Binlog-Protokoll

Binlog ist eine binäre Protokolldatei, die alle M...