注冊mySQL到JDBC驅動程序方法淺談
一、注冊方法(4種)
1)服務提供者框架:
符合JDBC 4.0規范的驅動程序包含了一個文件META-INF/services/java.sql.Driver,在這個文件中提供了JDBC驅動實現的類名。
例如:mysql-connector-java-5.1.40-bin.jar文件中就可以找到java.sql.Driver文件,用文本編輯器打開文件就可以看到:com.mysql.jdbc.Driver類。
JVM的服務提供者框架在啟動應用時就會注冊服務,例如:mySQL的JDBC驅動就會被注冊,而原代碼中的Class.forName("com.mysql.jdbc.Driver")仍然可以存在,但是不會起作用。
2)Class.forName("com.mysql.jdbc.Driver");
通過對類com.mysql.jdbc.Driver初始化,執行靜態初始化代碼,調用DriverManager注冊JDBC驅動。
注:通過setProperty的測試,確認類com.mysql.jdbc.Driver也沒有加載,那么靜態初始化代碼肯定被執行了,但是如果服務提供者框架已經注冊的服務,這里注冊會失敗,編程的預期是這樣的,可是理論上DriverManager.registerDriver可以重復注冊的,為什么這里不能重復注冊呢?
3)System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver";);
設置JVM的系統屬性,當JVM第一次加載DriverManager類時,會執行類的靜態初始化代碼,代碼中調用loadInitialDrivers()方法,就會加載設置的屬性對應的類,執行類的靜態初始化代碼完成注冊。
注:因為注冊的機制無法深入理解,只知道沒有加載過的類可以注冊成功,加載過的就不能重復注冊了。
注:setProperty必須在DriverManager第一次運行前才有效,說明”服務提供者”框架注冊服務時并沒有加載類,因為一旦加載類就會執行類的靜態初始化代碼,那么注冊JDBC驅動就一定會調用DriverManager類的靜態初始化代碼,那么setProperty就會失效,所以說明注冊服務是不加載類的。
4)DriverManager.registerDriver(new com.mysql.jdbc.Driver());
其實前面的2)和3)最終都是通過這個方法注冊的,但是這個方法就可以重復注冊。
注:對于重復注冊后,建立鏈接時使用哪個驅動我就不明白了,可以取消注冊,取消的關鍵字是基于創建的對象的,所以就算重名也不會出錯。
注:這種注冊方式沒有前面幾種好,因為這種注冊方式會在代碼中與需要注冊的驅動程序的類綁定,前面都可以通過配置參數實現注冊。
二、各自特點:
1)全自動。只要提供符合規范的JAR文件就可以了。
2)利用反射機制,將驅動類注入到代碼中,不需要與代碼綁定。
3)基于系統的屬性設置方法,將驅動類注入到代碼中,但是好像只能綁定一個JDBC驅動。
4)最終的注冊機制。會出現重復注冊,但是好像對程序沒影響,還需要與代碼綁定,驅動變了,必須修改代碼,維護成本過高,當然也是靈活性最好,管理最方便的。
以下是測試代碼:
import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; /** * @author 朱遠翔.Tom 測試JDBC驅動注冊 */ public class JDBCDriverTest { public static void main(String[] args) { Driver aDriver; Connection connection; Enumeration em; // “org.gjt.mm.mysql.Driver”是“com.mysql.jdbc.Driver”的子類,其構造函數就是調用父類的構造函數。 String driverString = "com.mysql.jdbc.Driver"; // String driverString = "org.gjt.mm.mysql.Driver"; String url = "jdbc:mysql://localhost/ElectricalStore?useSSL=false"; String username = "admin"; String password = "123456"; try {
// 將DriverManager的日志流輸出到Console窗口中,方便監控 // DriverManager.setLogStream(System.out); // DriverManager.println("------DriverManager logs start!------"); // 只是設置了一個JVM的系統屬性,并不建立JDBC驅動程序。 // 建立JDBC驅動是依賴系統第一次調用DriverManager類時,執行了這個類的靜態初始化代碼中的loadInitialDrivers(), // 加載驅動的方法會把設置的jdbc.drivers屬性對應的驅動類通過DriverManager.registerDriver注冊到JDBC中。 // 因此,必須放在DriverManager被第一次調用之間,也就是需要將前面那兩行代碼注釋掉 System.out.println("1.1> Tried to use setProperty."); System.setProperty("jdbc.drivers", driverString); System.out.println("---List of all jdbc drivers---"); em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration if (!em.hasMoreElements()) { System.out.println("There is no JDBC drivers"); } else { while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); System.out.println(aDriver); } } System.out.println("1.2> we tried to use Class.forName"); // Class.forName(driverString)在JavaSE 6.0后符合JDBC 4.0規范的驅動可以不用 // 基于服務提供機制( Service Provider mechanism), // 系統會自動搜索mysql-connector-java-???-bin.jar中的META-INF/services/java.sql.Driver // 這個文件會包含mysql jdbc驅動程序的入口:com.mysql.jdbc.Driver // 應用程序調用Class.forName()也不會出錯,只是什么都不會執行。 // 因為Class.forName()就是執行靜態初始化代碼,已經初始化過的類就無法激活這段代碼了 // System.setProperty("jdbc.drivers",driverString);與Class.forName()一樣。 try { Class.forName("com.mysql.fabric.jdbc.FabricMySQLDriver"); } catch (ClassNotFoundException e) { System.out.println("Driver not found"); } System.out.println("---List of all jdbc drivers---"); em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration if (!em.hasMoreElements()) { System.out.println("There is no JDBC drivers"); } else { while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); System.out.println(aDriver); } } System.out.println("1.3> we tried to use DriverManager.registerDriver"); // 手工注冊mySQL的JDBC驅動程序,也就出現了與mySQL綁定過緊的問題,如果以后需要更換驅動,就需要修改代碼。 // 系統容許出現重復注冊同樣的jdbc驅動類 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); DriverManager.registerDriver(new com.mysql.fabric.jdbc.FabricMySQLDriver()); DriverManager.registerDriver(new com.mysql.jdbc.Driver()); System.out.println("---List of all jdbc drivers---"); em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); System.out.println(aDriver); } System.out.println("<1.5> Deregister all JDBC drivers"); em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); DriverManager.deregisterDriver(aDriver); // 將已經注冊的驅動程序取消注冊 } em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration if (!em.hasMoreElements()) { System.out.println("2.1> Now, there is no JDBC driver"); } System.out.println("2.2> we tried to use Class.forName again"); try { Class.forName(driverString); } catch (ClassNotFoundException e) { System.out.println("Driver not found"); } try { Class.forName("com.mysql.fabric.jdbc.FabricMySQLDriver"); } catch (ClassNotFoundException e) { System.out.println("Driver not found"); } try { Class.forName(driverString); } catch (ClassNotFoundException e) { System.out.println("Driver not found"); } em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration if (!em.hasMoreElements()) { System.out.println("There is no JDBC drivers"); } else { System.out.println("---List of all jdbc drivers---"); while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); System.out.println(aDriver); } } System.out.println("2.3> we tried to use setProperty again"); System.setProperty("jdbc.drivers", "com.mysql.fabric.jdbc.FabricMySQLDriver"); em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration if (!em.hasMoreElements()) { System.out.println("There is no JDBC drivers"); } else { System.out.println("---List of all jdbc drivers---"); while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); System.out.println(aDriver); } } System.out.println("2.3> Tried to use DriverManager.registerDriver again"); DriverManager.registerDriver(new com.mysql.jdbc.Driver()); DriverManager.registerDriver(new com.mysql.fabric.jdbc.FabricMySQLDriver()); DriverManager.registerDriver(new com.mysql.jdbc.Driver()); System.out.println("---List of all jdbc drivers---"); em = DriverManager.getDrivers(); // 獲取已加載JDBC驅動程序的Enumeration if (!em.hasMoreElements()) { System.out.println("There is no JDBC drivers"); } else { while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); System.out.println(aDriver); } } System.out.print("3.1> Tried to establish a connection: "); connection = DriverManager.getConnection(url, username, password); System.out.println(connection); } catch (SQLException e) { System.out.println("Cannot registered the mysql jdbc driver"); } System.out .println("jdbc.drivers property: " + System.getProperty("jdbc.drivers", "nothing")); } }
posted on 2016-10-05 20:16 zYx.Tom 閱讀(976) 評論(0) 編輯 收藏 所屬分類: 1.Java世界