JAVA JDBC connection


前言:自己的小理解和大部分javasec內容

JDBC

什么是JDBC?

JDBC本質:官方定義的一套操作所有關系型數據庫的規則,即接口。 各個數據庫廠商去實現了這個JDBC的接口,提供數據庫驅動jar包,我們可以使用這套接口JDBC編程,真正執行代碼的是驅動jar包中的實現類

什么是"真正執行代碼的是驅動jar包中的實現類",其實就是一個類去實現官方寫的接口中的方法,這樣就是一個實現類!

那么廠商們要實現哪個哪個接口呢? java.sql.Driver

跟進去看下,如下的方法都是廠商們一定需要實現的方法!!!

public interface Driver //這是一個接口,不用說,要不然其他廠商如何實現呢!
Connection connect(String url, java.util.Properties info)
boolean acceptsURL(String url) //還能判斷是否是正規的數據庫協議
DriverPropertyInfo[] getPropertyInfo // 該方法可以獲得一些驅動的相關信息放到DriverPropertyInfo數組中
int getMajorVersion(); //獲取主版本信息
int getMinorVersion(); //獲取副版本信息
boolean jdbcCompliant(); //判斷驅動程序是否為正版JDBC
public Logger getParentLogger() //返回此驅動程序使用的所有記錄器的父記錄器

可以看下Mysql中的驅動包是如何寫的,如下顯示,這里它通過繼承NonRegisteringDriver類來實現了java.sql.Driver的接口

java.sql.DriverManager

Java通過java.sql.DriverManager來管理所有數據庫的驅動注冊,所以如果想要建立數據庫連接需要先在java.sql.DriverManager中注冊registerDriver對應的驅動類,然后調用getConnection方法才能連接上數據庫。

跟進去簡單的了解下DriverManager這個類的屬性和方法

這是一個公有類public class DriverManager

如下屬性:注冊的JDBC驅動程序列表

    // List of registered JDBC drivers
    private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); //這個是用來保存已經注冊過的驅動
    private static volatile int loginTimeout = 0;
    private static volatile java.io.PrintWriter logWriter = null;
    private static volatile java.io.PrintStream logStream = null;

一個靜態代碼塊:

    static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

還有一些關於日志的操作:

public static java.io.PrintWriter getLogWriter()
public static void setLogWriter(java.io.PrintWriter out)
....
....

獲取數據庫的連接:

public static Connection getConnection(String url, java.util.Properties info)
public static Connection getConnection(String url, String user, String password)
public static Connection getConnection(String url)
private static Connection getConnection(String url, java.util.Properties info, Class<?> caller)

驅動的相關操作:

public static Driver getDriver(String url) //獲取驅動
public static synchronized void registerDriver(java.sql.Driver driver) //注冊驅動1
public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) //注冊驅動2
public static synchronized void deregisterDriver(Driver driver) //取消驅動

一個概念:Java通過java.sql.DriverManager來管理所有數據庫的驅動注冊,所以如果想要建立數據庫連接需要先在java.sql.DriverManager中注冊對應的驅動類,然后調用getConnection方法才能連接上數據庫。

java.sql.DriverManager.getConnection(xx)其實就是間接的調用了java.sql.Driver類的connect方法實現數據庫連接的。數據庫連接成功后會返回一個叫做java.sql.Connection的數據庫連接對象,一切對數據庫的查詢操作都將依賴於這個Connection對象。

JDBC連接數據庫的一般步驟:

1、注冊驅動,Class.forName("數據庫驅動的類名")
2、獲取連接,DriverManager.getConnection(xxx)

正常實現的代碼如下

        Class.forName("com.mysql.jdbc.Driver");
        String URL = "jdbc:mysql://localhost:3306/mysql";
        String USERNAME = "root";
        String PASSWORD = "123456";
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);

我自己學的時候反正是有疑問的,為什么注冊用Class.forName("com.mysql.jdbc.Driver");來實現,然后就是DriverManager.getConnection為什么能夠獲得Mysql驅動包中的connection對象

這兩個問題得解決!

為什么Class.forName能夠實現注冊驅動

那么直接跟進com.mysql.jdbc.Driver的Driver類中去觀察

看下如下的內容,這是一個靜態代碼塊,並且Class.forName("com.mysql.jdbc.Driver")使用的時候會觸發類加載,從而執行該靜態代碼塊,那么也就可以說明了,為什么能夠Class.forName("com.mysql.jdbc.Driver")能夠注冊驅動!

提醒,如果想拿到對應類型的Class實例,但是又不想觸發類加載執行靜態代碼塊的話,下面兩種方法可以解決:

1、使用Class.forName("xxxx", false, loader)方法,將第二個參數傳入false。

2、ClassLoader.load("xxxx");

DriverManager.getConnection為什么能夠獲得Mysql

那么也從源碼中觀察,老樣子跟進DriverManager中,靜態代碼塊執行的是DriverManager.registerDriver(new Driver());

繼續跟registerDriver方法,如下圖所示,它會將Mysql自身Driver實例化然后放到registerDriver中

最后還會添加到registeredDrivers屬性中

然后現在就是Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);

我們可以看下DriverManager.getConnection的方法是怎么樣的,如下圖所示,它會將賬號密碼這些都存儲起來然后放到一個info對象中,再將info作為參數傳入getConnection中

跟進去看,重點是如下的紅框處,它的for循環會遍歷registeredDrivers數組,取出DriverInfo類型的aDriver變量,DriverInfo這個就是之前存儲到registeredDrivers數組中的內容,此時的aDriver.driver就是已經實例化的Driver對象(Mysql,Mssql等等),最后調用它們實現Driver接口之后的connect方法,返回一個connection的對象!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM