注冊mySQL到JDBC驅(qū)動程序方法淺談
一、注冊方法(4種)
1)服務提供者框架:
符合JDBC 4.0規(guī)范的驅(qū)動程序包含了一個文件META-INF/services/java.sql.Driver,在這個文件中提供了JDBC驅(qū)動實現(xiàn)的類名。
例如:mysql-connector-java-5.1.40-bin.jar文件中就可以找到java.sql.Driver文件,用文本編輯器打開文件就可以看到:com.mysql.jdbc.Driver類。
JVM的服務提供者框架在啟動應用時就會注冊服務,例如:mySQL的JDBC驅(qū)動就會被注冊,而原代碼中的Class.forName("com.mysql.jdbc.Driver")仍然可以存在,但是不會起作用。
2)Class.forName("com.mysql.jdbc.Driver");
通過對類com.mysql.jdbc.Driver初始化,執(zhí)行靜態(tài)初始化代碼,調(diào)用DriverManager注冊JDBC驅(qū)動。
注:通過setProperty的測試,確認類com.mysql.jdbc.Driver也沒有加載,那么靜態(tài)初始化代碼肯定被執(zhí)行了,但是如果服務提供者框架已經(jīng)注冊的服務,這里注冊會失敗,編程的預期是這樣的,可是理論上DriverManager.registerDriver可以重復注冊的,為什么這里不能重復注冊呢?
3)System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver";);
設置JVM的系統(tǒng)屬性,當JVM第一次加載DriverManager類時,會執(zhí)行類的靜態(tài)初始化代碼,代碼中調(diào)用loadInitialDrivers()方法,就會加載設置的屬性對應的類,執(zhí)行類的靜態(tài)初始化代碼完成注冊。
注:因為注冊的機制無法深入理解,只知道沒有加載過的類可以注冊成功,加載過的就不能重復注冊了。
注:setProperty必須在DriverManager第一次運行前才有效,說明”服務提供者”框架注冊服務時并沒有加載類,因為一旦加載類就會執(zhí)行類的靜態(tài)初始化代碼,那么注冊JDBC驅(qū)動就一定會調(diào)用DriverManager類的靜態(tài)初始化代碼,那么setProperty就會失效,所以說明注冊服務是不加載類的。
4)DriverManager.registerDriver(new com.mysql.jdbc.Driver());
其實前面的2)和3)最終都是通過這個方法注冊的,但是這個方法就可以重復注冊。
注:對于重復注冊后,建立鏈接時使用哪個驅(qū)動我就不明白了,可以取消注冊,取消的關鍵字是基于創(chuàng)建的對象的,所以就算重名也不會出錯。
注:這種注冊方式?jīng)]有前面幾種好,因為這種注冊方式會在代碼中與需要注冊的驅(qū)動程序的類綁定,前面都可以通過配置參數(shù)實現(xiàn)注冊。
二、各自特點:
1)全自動。只要提供符合規(guī)范的JAR文件就可以了。
2)利用反射機制,將驅(qū)動類注入到代碼中,不需要與代碼綁定。
3)基于系統(tǒng)的屬性設置方法,將驅(qū)動類注入到代碼中,但是好像只能綁定一個JDBC驅(qū)動。
4)最終的注冊機制。會出現(xiàn)重復注冊,但是好像對程序沒影響,還需要與代碼綁定,驅(qū)動變了,必須修改代碼,維護成本過高,當然也是靈活性最好,管理最方便的。
以下是測試代碼:
import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; /** * @author 朱遠翔.Tom 測試JDBC驅(qū)動注冊 */ public class JDBCDriverTest { public static void main(String[] args) { Driver aDriver; Connection connection; Enumeration em; // “org.gjt.mm.mysql.Driver”是“com.mysql.jdbc.Driver”的子類,其構造函數(shù)就是調(diào)用父類的構造函數(shù)。 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窗口中,方便監(jiān)控 // DriverManager.setLogStream(System.out); // DriverManager.println("------DriverManager logs start!------"); // 只是設置了一個JVM的系統(tǒng)屬性,并不建立JDBC驅(qū)動程序。 // 建立JDBC驅(qū)動是依賴系統(tǒng)第一次調(diào)用DriverManager類時,執(zhí)行了這個類的靜態(tài)初始化代碼中的loadInitialDrivers(), // 加載驅(qū)動的方法會把設置的jdbc.drivers屬性對應的驅(qū)動類通過DriverManager.registerDriver注冊到JDBC中。 // 因此,必須放在DriverManager被第一次調(diào)用之間,也就是需要將前面那兩行代碼注釋掉 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驅(qū)動程序的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規(guī)范的驅(qū)動可以不用 // 基于服務提供機制( Service Provider mechanism), // 系統(tǒng)會自動搜索mysql-connector-java-???-bin.jar中的META-INF/services/java.sql.Driver // 這個文件會包含mysql jdbc驅(qū)動程序的入口:com.mysql.jdbc.Driver // 應用程序調(diào)用Class.forName()也不會出錯,只是什么都不會執(zhí)行。 // 因為Class.forName()就是執(zhí)行靜態(tài)初始化代碼,已經(jīng)初始化過的類就無法激活這段代碼了 // 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驅(qū)動程序的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驅(qū)動程序,也就出現(xiàn)了與mySQL綁定過緊的問題,如果以后需要更換驅(qū)動,就需要修改代碼。 // 系統(tǒng)容許出現(xiàn)重復注冊同樣的jdbc驅(qū)動類 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驅(qū)動程序的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驅(qū)動程序的Enumeration while (em.hasMoreElements()) { aDriver = (Driver) em.nextElement(); DriverManager.deregisterDriver(aDriver); // 將已經(jīng)注冊的驅(qū)動程序取消注冊 } em = DriverManager.getDrivers(); // 獲取已加載JDBC驅(qū)動程序的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驅(qū)動程序的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驅(qū)動程序的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驅(qū)動程序的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 閱讀(981) 評論(0) 編輯 收藏 所屬分類: 1.Java世界