最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")

 更新時(shí)間:2019年04月01日 10:22:24   作者:寧愿呢  
這篇文章主要介紹了使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下

引言

如果熟悉使用JDBC來連接數(shù)據(jù)庫的同學(xué)一定很清楚連接數(shù)據(jù)庫的代碼中一定會(huì)有依據(jù)Class.forName

("com.mysql.jdbc.Driver");
  public static Connection getConnection() throws ClassNotFoundException, SQLException {
    if(connection == null){
      Class.forName("com.mysql.jdbc.Driver");
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
    }
    return connection;
  }

之前沒有想過為什么需要有這么一個(gè)語句,都是按照文檔直接這么做的,在這篇文章中我來試著解釋這么做的原因。

類加載機(jī)制

在這之前我們先來說下Java中的類加載機(jī)制。

在Java中如果想要使用一個(gè)類,則必須要求該類已經(jīng)被加載到Jvm中,加載的過程實(shí)際上就是通過類的全限定名來獲取定義該類二進(jìn)制字節(jié)流,然后將這個(gè)字節(jié)流所表示的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)換為方法去的動(dòng)態(tài)運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)。同時(shí)在在內(nèi)存中實(shí)例化一個(gè)java.lang.Class對(duì)象,作為方法區(qū)中該類的數(shù)據(jù)訪問入口(供我們使用)。

而會(huì)觸發(fā)類加載的會(huì)有如下幾種情況(引用自<<深入理解Java虛擬機(jī)>>):

1.遇到new、getstatic、putstatic或invokestatic這4條字節(jié)碼指令時(shí),如果類沒有進(jìn)行過初始化,則需要先觸發(fā)其初始化。生成這4條指令的最常見的Java代碼場(chǎng)景是:使用new關(guān)鍵字實(shí)例化對(duì)象的時(shí)候、讀取或設(shè)置一個(gè)類的靜態(tài)字段(被final修飾、已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時(shí)候,以及調(diào)用一個(gè)類的靜態(tài)方法的時(shí)候。

2.使用java.lang.reflect包的方法對(duì)類進(jìn)行反射調(diào)用的時(shí)候,如果類沒有進(jìn)行過初始化,則需要先觸發(fā)其初始化。

3.當(dāng)初始化一個(gè)類的時(shí)候,如果發(fā)現(xiàn)其父類還沒有進(jìn)行過初始化,則需要先觸發(fā)其父類的初始化。

4.當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶需要指定一個(gè)要執(zhí)行的主類(包含main()方法的那個(gè)類),虛擬機(jī)會(huì)先初始化這個(gè)主類。

Class.forName

在Java官方文檔中對(duì)Class.forName的解釋為在運(yùn)行時(shí)動(dòng)態(tài)的加載一個(gè)類,返回值為生成的Class對(duì)象。

那么很明顯在jdbc中使用Class.forName("com.mysql.jdbc.Driver");僅僅就是將com.mysql.jdbc.Driver類加載到Jvm中了,這個(gè)原因大多數(shù)人應(yīng)該都知道。

但是我們要知道Class.forName貌似只是對(duì)類進(jìn)行了加載,我們甚至都沒有對(duì)返回的Class對(duì)象做任何操作,那么我們?yōu)槭裁春竺婢涂梢灾苯佑昧四兀?/p>

首先看Class.forName調(diào)用了native方法forName0(...);

@CallerSensitive
public static Class<?> forName(String className)
      throws ClassNotFoundException {
  Class<?> caller = Reflection.getCallerClass();
  return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

private static native Class<?> forName0(String name, boolean initialize,ClassLoader loader,Class<?> caller);

要注意forName0中有一個(gè)關(guān)鍵的參數(shù)boolean initialize,;該參數(shù)用來標(biāo)識(shí)在將該類加載后是否進(jìn)行初始化操作??梢钥吹酱a中是true,就表示會(huì)進(jìn)行初始化操作。

初始化過程實(shí)際上就是對(duì)變量賦值(不是賦初值,不會(huì)調(diào)用構(gòu)造函數(shù))的過程。包含所有類變量的賦值以及靜態(tài)代碼語句塊的執(zhí)行代碼,包括對(duì)父類的初始化。

再看com.mysql.jdbc.Driver驅(qū)動(dòng)類:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
  public Driver() throws SQLException {
  }

  static {
    try {
      DriverManager.registerDriver(new Driver());
    } catch (SQLException var1) {
      throw new RuntimeException("Can't register driver!");
    }
  }
}

該類中定義了一個(gè)靜態(tài)代碼塊,靜態(tài)代碼快中創(chuàng)建了一個(gè)驅(qū)動(dòng)類實(shí)例注冊(cè)給了DriverManager,而靜態(tài)代碼塊的內(nèi)容會(huì)在初始化的過程中執(zhí)行,所以才能通過DriverManager.getConnection直接獲取一個(gè)連接。

其他加載類方法

我們需要明白的是在Java中并不是只有通過Class.forName()才能顯示的加載類。那么為什么不使用其他的加載方法而偏偏選擇Class.forName()呢?

ClassLoader.getSystemClassLoader().loadClass()

通過類加載器也可以將一個(gè)類加載到Jvm中。通過ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");也可以加載驅(qū)動(dòng)類。

但是如果我們深入看下loadClass的實(shí)現(xiàn):

public Class<?> loadClass(String name) throws ClassNotFoundException {
  return loadClass(name, false);
}

protected Class<?> loadClass(String name, boolean resolve);

可以看到其調(diào)用了一個(gè)重載的方法,該方法也有一個(gè)boolean類型的變量boolean resolve,調(diào)用時(shí)默認(rèn)為false。該參數(shù)用于標(biāo)識(shí)是否對(duì)加載后的類進(jìn)行鏈接操作,如果不進(jìn)行連接操作則不會(huì)有初始化的操作。

所以如果使用這種加載類方式的話理論上來說是沒發(fā)使用該驅(qū)動(dòng)類的。

new關(guān)鍵字

也可以使用new關(guān)鍵字進(jìn)行加載操作,在使用new關(guān)鍵字時(shí)會(huì)查看該類是否已經(jīng)被加載,如果沒有被加載的話則會(huì)進(jìn)行加載操作。所以我們的類中也可以這樣寫:

public static Connection getConnection() throws ClassNotFoundException, SQLException {
  if(connection == null){
    new Driver();//會(huì)自動(dòng)調(diào)用靜態(tài)代碼塊
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxx");
  }
  return connection;
}

但是實(shí)際上因?yàn)樵隍?qū)動(dòng)類的靜態(tài)代碼快中實(shí)際上已經(jīng)有了實(shí)例化對(duì)象并注冊(cè)到DriverMananger中的操作。所以這里根本就沒有在實(shí)例化一個(gè)對(duì)象的過程。使用Class.forName即可,這也算是一個(gè)優(yōu)化的過程吧。

可以不使用Class.forName("com.mysql.jdbc.Driver")

在測(cè)試的過程中發(fā)現(xiàn)即使不顯示的使用Class.forName("com.mysql.jdbc.Driver")也能夠連接到數(shù)據(jù)庫,一時(shí)間覺得很奇怪。

深入跟蹤代碼后發(fā)現(xiàn)實(shí)際上只要我們引入了mysql的驅(qū)動(dòng)包,那么在使用時(shí)會(huì)根據(jù)驅(qū)動(dòng)包下提供的配置文件默認(rèn)的創(chuàng)建一個(gè)類。

所以實(shí)際上只要引入了該驅(qū)動(dòng)包,那么使用jdbc是可以直接通過DriverManage來獲取連接。

public static Connection getConnection() SQLException {
  return DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
}

總結(jié)

以上所述是小編給大家介紹的為什么使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver") ,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • MySQL使用命令行備份數(shù)據(jù)的方法詳解

    MySQL使用命令行備份數(shù)據(jù)的方法詳解

    由于長期使用測(cè)試環(huán)境的數(shù)據(jù)庫,時(shí)不時(shí)會(huì)有臟數(shù)據(jù)刪除不干凈,對(duì)此很需要一個(gè)實(shí)時(shí)將生產(chǎn)庫的數(shù)據(jù)定期備份一份,防止生產(chǎn)庫中會(huì)有臟數(shù)據(jù)進(jìn)來,所以本文給大家介紹了MySQL使用命令行備份數(shù)據(jù)的方法,需要的朋友可以參考下
    2024-02-02
  • MySQL 8.0.13 下載安裝教程圖文詳解

    MySQL 8.0.13 下載安裝教程圖文詳解

    這篇文章主要介紹了MySQL 8.0.13 下載安裝教程,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • Window10下安裝 mysql5.7圖文教程(解壓版)

    Window10下安裝 mysql5.7圖文教程(解壓版)

    這篇文章主要介紹了Window10下安裝 mysql5.7圖文教程(解壓版),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2016-08-08
  • B-樹的刪除過程介紹

    B-樹的刪除過程介紹

    今天小編就為大家分享一篇關(guān)于B-樹的刪除過程介紹,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • mysql exists與not exists實(shí)例詳解

    mysql exists與not exists實(shí)例詳解

    這篇文章主要介紹了mysql exists與not exists實(shí)例詳解的相關(guān)資料,鑒于 not exists 的效率往往要高于 not in , 所以一般情況下會(huì)使用前者替代后者,需要的朋友可以參考下
    2017-07-07
  • 防止web項(xiàng)目中的SQL注入

    防止web項(xiàng)目中的SQL注入

    這篇文章介紹了防止web項(xiàng)目中的SQL注入,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。需要的朋友可以收藏下,方便下次瀏覽觀看
    2021-12-12
  • MySQL分區(qū)表的使用

    MySQL分區(qū)表的使用

    本文詳細(xì)介紹了在MySQL中創(chuàng)建分區(qū)表的方法和注意事項(xiàng),包括Range和List兩種常見分區(qū)類型的具體操作流程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • MySQL命令行方式進(jìn)行數(shù)據(jù)備份與恢復(fù)

    MySQL命令行方式進(jìn)行數(shù)據(jù)備份與恢復(fù)

    本文主要介紹了MySQL命令行方式進(jìn)行數(shù)據(jù)備份與恢復(fù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • MySQL root賬號(hào)遠(yuǎn)程新建數(shù)據(jù)庫報(bào)錯(cuò)1044問題及解決方法

    MySQL root賬號(hào)遠(yuǎn)程新建數(shù)據(jù)庫報(bào)錯(cuò)1044問題及解決方法

    這篇文章主要介紹了MySQL root賬號(hào)遠(yuǎn)程新建數(shù)據(jù)庫報(bào)錯(cuò)1044問題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • MySQL Galera Cluster部署與使用

    MySQL Galera Cluster部署與使用

    MySQLGaleraCluster是一種高可用、同步復(fù)制的數(shù)據(jù)庫解決方案,本文主要介紹了MySQL Galera Cluster 部署與使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03

最新評(píng)論

弋阳县| 樟树市| 浦城县| 离岛区| 武平县| 北安市| 分宜县| 昌乐县| 南充市| 马山县| 新兴县| 汕头市| 英山县| 红安县| 贞丰县| 九江县| 建昌县| 鄂托克前旗| 清流县| 迁安市| 乡城县| 黄浦区| 奇台县| 涟源市| 安达市| 仙桃市| 屏边| 临武县| 北碚区| 兰溪市| 宜兰县| 台江县| 澎湖县| 汶川县| 新巴尔虎左旗| 海林市| 梁河县| 社会| 海林市| 葫芦岛市| 永定县|