數(shù)據(jù)庫連接JDBC與數(shù)據(jù)庫連接池c3p0讨衣、dhcp的關(guān)系詳細(xì)介紹

數(shù)據(jù)庫連接JDBC

在Java中束世,數(shù)據(jù)庫存取技術(shù)可分為如下幾類:

JDBC直接訪問數(shù)據(jù)庫JDO技術(shù)第三方O/R工具薛耻,如Hibernate, ibatis 等JDBC是java訪問數(shù)據(jù)庫的基石输钩,JDO, Hibernate等只是更好的封裝了JDBC。

JDBC(Java Database Connectivity)是一個獨立于特定數(shù)據(jù)庫管理系統(tǒng)仲智、通用的SQL數(shù)據(jù)庫存取和操作的公共接口(一組API)买乃,定義了用來訪問數(shù)據(jù)庫的標(biāo)準(zhǔn)Java類庫,(java.sql,javax.sql)使用這個類庫可以以一種標(biāo)準(zhǔn)的方法钓辆、方便地訪問數(shù)據(jù)庫資源剪验。JDBC為訪問不同的數(shù)據(jù)庫提供了一種統(tǒng)一的途徑,為開發(fā)者屏蔽了一些細(xì)節(jié)問題前联。JDBC的目標(biāo)是使Java程序員使用JDBC可以連接任何提供了JDBC驅(qū)動程序的數(shù)據(jù)庫系統(tǒng)功戚,這樣就使得程序員無需對特定的數(shù)據(jù)庫系統(tǒng)的特點有過多的了解,從而大大簡化和加快了開發(fā)過程似嗤。

image.png

當(dāng)然也可以不使用統(tǒng)一的JDBC接口分別使用不同的數(shù)據(jù)庫廠商各自的驅(qū)動啸臀,但這樣就不能體現(xiàn)Java的可移植性了。

JDBC是sun公司提供一套用于數(shù)據(jù)庫操作的接口烁落,java程序員只需要面向這套接口編程即可乘粒。不同的數(shù)據(jù)庫廠商,需要針對這套接口伤塌,提供不同實現(xiàn)灯萍。不同的實現(xiàn)的集合,即為不同數(shù)據(jù)庫的驅(qū)動每聪。-----面向接口編程

JDBC:一套用于數(shù)據(jù)庫操作的接口

JDBC驅(qū)動:需要針對這套接口旦棉,提供不同實現(xiàn)齿风。不同的實現(xiàn)的集合,即為不同數(shù)據(jù)庫的驅(qū)動

JDBC接口(API)包括兩個層次:

面向應(yīng)用的API:Java API绑洛,抽象接口救斑,供應(yīng)用程序開發(fā)人員使用(連接數(shù)據(jù)庫,執(zhí)行SQL語句诊笤,獲得結(jié)果)系谐。

面向數(shù)據(jù)庫的API:Java Driver API,供開發(fā)商開發(fā)數(shù)據(jù)庫驅(qū)動程序用讨跟。

這是通過JDBC連接數(shù)據(jù)庫的幾種方式,也是從繁到簡的一個過程:

JDBCTest.java

public class JDBCTest {
     
    //版本4.0 最終版
    @Test
    public void test4() throws Exception{
        Properties pros = new Properties();
        pros.load(this.getClass().getClassLoader().getResourceAsStream("com/atguigu/jdbc/jdbc.properties"));
        String driverClassName = pros.getProperty("driverClassName");
        String url = pros.getProperty("url");
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
         
        //1. 加載驅(qū)動
        Class.forName(driverClassName);
         
        //2. 獲取連接
        Connection conn = DriverManager.getConnection(url, user, password);
         
        System.out.println(conn);
    }
     
    //版本3.0 
    @Test
    public void test3() throws Exception{
        String driverClassName = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1:3306/test";
        String user = "root";
        String password = "123456";
        /*
         * 通常不用顯式調(diào)用 DriverManager 類的 registerDriver() 
         * 方法來注冊驅(qū)動程序類的實例纪他,因為 Driver 接口的驅(qū)動程序類都包含了靜態(tài)代碼塊,
         * 在這個靜態(tài)代碼塊中晾匠,隨類加載而加載茶袒,即Class類加載時就加載了驅(qū)動,所以它會
         * 會調(diào)用 DriverManager.registerDriver() 方法來注冊自身的一個實例
         */
        //1. 加載驅(qū)動
        Class.forName(driverClassName);
         
        //2. 獲取連接
        Connection conn = DriverManager.getConnection(url, user, password);
         
        System.out.println(conn);
    }
     
    //版本2.0 利用 DriverManager(驅(qū)動管理類)凉馆,獲取數(shù)據(jù)庫連接
    @Test
    public void test2() throws Exception{
        String driverClassName = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1:3306/test";
        String user = "root";
        String password = "123456";
         
        //1. 注冊驅(qū)動
        Driver driver = null;
         
        Class clazz = Class.forName(driverClassName);
         
        driver = (Driver) clazz.newInstance();
         
        DriverManager.registerDriver(driver);
         
        //2. 獲取連接
        Connection conn = DriverManager.getConnection(url, user, password);
         
        System.out.println(conn);
    }
     
    //版本1.0 利用反射薪寓,根據(jù) MySQL 廠商提供的驅(qū)動,獲取 MySQL 數(shù)據(jù)庫的連接
    @Test
    public void test1() throws Exception{
        String driverClassName = "com.mysql.jdbc.Driver";
         
        //1. 獲取驅(qū)動
        Driver driver = null;
         
        Class clazz = Class.forName(driverClassName);
         
        driver = (Driver) clazz.newInstance();
         
        //2. 獲取連接
        String url = "jdbc:mysql://127.0.0.1:3306/test";
         
        Properties info = new Properties();
        info.setProperty("user", "root");
        info.setProperty("password", "123456");
         
        Connection conn = driver.connect(url, info);
         
        System.out.println(conn);
    }
 
}

數(shù)據(jù)庫連接池c3p0澜共、dhcp

在使用開發(fā)基于數(shù)據(jù)庫的web程序時向叉,傳統(tǒng)的模式(JDBC)基本是按以下步驟:

在主程序(如servlet、beans)中建立數(shù)據(jù)庫連接進(jìn)行sql操作斷開數(shù)據(jù)庫連接但這種模式開發(fā)嗦董,存在的問題:

普通的JDBC數(shù)據(jù)庫連接使用 DriverManager 來獲取母谎,每次向數(shù)據(jù)庫建立連接的時候都要將 Connection 加載到內(nèi)存中,再驗證用戶名和密碼(得花費0.05s~1s的時間)京革。需要數(shù)據(jù)庫連接的時候奇唤,就向數(shù)據(jù)庫要求一個,執(zhí)行完成后再斷開連接匹摇。這樣的方式將會消耗大量的資源和時間咬扇。數(shù)據(jù)庫的連接資源并沒有得到很好的重復(fù)利用.若同時有幾百人甚至幾千人在線,頻繁的進(jìn)行數(shù)據(jù)庫連接操作將占用很多的系統(tǒng)資源廊勃,嚴(yán)重的甚至?xí)斐煞?wù)器的崩潰懈贺。

對于每一次數(shù)據(jù)庫連接,使用完后都得斷開供搀。否則隅居,如果程序出現(xiàn)異常而未能關(guān)閉,將會導(dǎo)致數(shù)據(jù)庫系統(tǒng)中的內(nèi)存泄漏葛虐,最終將導(dǎo)致重啟數(shù)據(jù)庫胎源。

這種開發(fā)不能控制被創(chuàng)建的連接對象數(shù),系統(tǒng)資源會被毫無顧及的分配出去屿脐,如連接過多涕蚤,也可能導(dǎo)致內(nèi)存泄漏宪卿,服務(wù)器崩潰。

為解決傳統(tǒng)開發(fā)中的數(shù)據(jù)庫連接問題万栅,可以采用數(shù)據(jù)庫連接池技術(shù)佑钾。

數(shù)據(jù)庫連接池的基本思想就是為數(shù)據(jù)庫連接建立一個“緩沖池”。預(yù)先在緩沖池中放入一定數(shù)量的連接烦粒,當(dāng)需要建立數(shù)據(jù)庫連接時休溶,只需從“緩沖池”中取出一個,使用完畢之后再放回去扰她。

數(shù)據(jù)庫連接池負(fù)責(zé)分配兽掰、管理和釋放數(shù)據(jù)庫連接,它允許應(yīng)用程序重復(fù)使用一個現(xiàn)有的數(shù)據(jù)庫連接徒役,而不是重新建立一個孽尽。

數(shù)據(jù)庫連接池在初始化時將創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接放到連接池中,這些數(shù)據(jù)庫連接的數(shù)量是由最小數(shù)據(jù)庫連接數(shù)來設(shè)定的忧勿。無論這些數(shù)據(jù)庫連接是否被使用杉女,連接池都將一直保證至少擁有這么多的連接數(shù)量。連接池的最大數(shù)據(jù)庫連接數(shù)量限定了這個連接池能占有的最大連接數(shù)鸳吸,當(dāng)應(yīng)用程序向連接池請求的連接數(shù)超過最大連接數(shù)量時熏挎,這些請求將被加入到等待隊列中。

JDBC 的數(shù)據(jù)庫連接池使用 javax.sql.DataSource 來表示晌砾,DataSource 只是一個接口婆瓜,該接口通常由服務(wù)器(Weblogic, WebSphere, Tomcat)提供實現(xiàn),也有一些開源組織提供實現(xiàn):

DBCP 數(shù)據(jù)庫連接池C3P0 數(shù)據(jù)庫連接池DataSource 通常被稱為數(shù)據(jù)源贡羔,它包含連接池和連接池管理兩個部分,習(xí)慣上也經(jīng)常把 DataSource 稱為連接池

DataSource用來取代DriverManager來獲取Connection个初,獲取速度快乖寒,同時可以大幅度提高數(shù)據(jù)庫訪問速度。

DHCP數(shù)據(jù)源

DBCP 是 Apache 軟件基金組織下的開源連接池實現(xiàn)院溺,該連接池依賴該組織下的另一個開源系統(tǒng):Common-pool. 如需使用該連接池實現(xiàn)楣嘁,應(yīng)在系統(tǒng)中增加如下兩個 jar 文件:

Commons-dbcp.jar:連接池的實現(xiàn)

Commons-pool.jar:連接池實現(xiàn)的依賴庫

Tomcat 的連接池正是采用該連接池來實現(xiàn)的。該數(shù)據(jù)庫連接池既可以與應(yīng)用服務(wù)器整合使用珍逸,也可由應(yīng)用程序獨立使用逐虚。

數(shù)據(jù)源和數(shù)據(jù)庫連接不同,數(shù)據(jù)源無需創(chuàng)建多個谆膳,它是產(chǎn)生數(shù)據(jù)庫連接的工廠叭爱,因此整個應(yīng)用只需要一個數(shù)據(jù)源即可。

當(dāng)數(shù)據(jù)庫訪問結(jié)束后漱病,程序還是像以前一樣關(guān)閉數(shù)據(jù)庫連接:conn.close(); 但上面的代碼并沒有關(guān)閉數(shù)據(jù)庫的物理連接买雾,它僅僅把數(shù)據(jù)庫連接釋放把曼,歸還給了數(shù)據(jù)庫連接池。

兩種連接池分別有兩種方式創(chuàng)建數(shù)據(jù)庫的連接

image.png

DataSourceTest.java

public class DataSourceTest {
     
    //使用 C3P0 方式二:
    @Test
    public void test4() throws SQLException{
        DataSource ds = new ComboPooledDataSource("helloc3p0");
         
        Connection conn = ds.getConnection();
         
        System.out.println(conn);
    }
     
    //使用 C3P0 方式一:
    @Test
    public void test3() throws Exception{
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        cpds.setDriverClass("com.mysql.jdbc.Driver");
        cpds.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test");
        cpds.setUser("root");
        cpds.setPassword("123456");
      
        Connection conn = cpds.getConnection();
         
        System.out.println(conn);
    }
     
    //使用 DBCP 方式二:
    @Test
    public void test2() throws Exception{
        Properties pros = new Properties();
        pros.load(DataSourceTest.class.getClassLoader().getResourceAsStream("dbcp.properties"));
         
        DataSource ds = BasicDataSourceFactory.createDataSource(pros);
         
        Connection conn = ds.getConnection();
         
        System.out.println(conn);
    }
     
    //使用 DBCP 方式一:
    @Test
    public void test1() throws SQLException{
        BasicDataSource bds = new BasicDataSource();
        bds.setDriverClassName("com.mysql.jdbc.Driver");
        bds.setUrl("jdbc:mysql://127.0.0.1:3306/test");
        bds.setUsername("root");
        bds.setPassword("123456");
         
        bds.setInitialSize(10);
        bds.setMaxActive(10);
         
        Connection conn = bds.getConnection();
         
        System.out.println(conn);
         
        //將連接放回到連接池中
        conn.close();
    }
 
}

使用方式二的c3p0需要一個配置文件(當(dāng)然也可以用屬性文件)漓穿,且配置文件的名字必須是c3p0-config.xml嗤军,因為數(shù)據(jù)庫廠商底層是根據(jù)key-value來封裝數(shù)據(jù)的,所以會根據(jù)這個key來進(jìn)行匹配讀取晃危,而且必須放在src的路徑下叙赚,因為讀取是通過類加載器的方式進(jìn)行讀取的。使用方式二的dhcp需要一個屬性文件和jdbc的屬性文件大致一樣僚饭,就不多贅述了

c3p0-config.xml

<c3p0-config>
  <named-config name="helloc3p0"> 
   
    <!-- 連接數(shù)據(jù)庫的四個字符串 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/test</property>
    <property name="user">root</property>
    <property name="password">123456</property>
   
    <!-- 若連接池滿了一次增長幾個 -->
    <property name="acquireIncrement">5</property>
     
    <!-- 連接池初始大小 -->
    <property name="initialPoolSize">10</property>
     
    <!-- 連接池中最小連接數(shù) -->
    <property name="minPoolSize">5</property>
     
    <!-- 連接池中最大連接數(shù) -->
    <property name="maxPoolSize">10</property>
 
    <!-- 整個連接池中最多管理的 Statement 的個數(shù) -->
    <property name="maxStatements">10</property> 
     
    <!-- 連接池中每個連接最多管理的 Statement 的個數(shù) -->
    <property name="maxStatementsPerConnection">2</property>
 
  </named-config>
</c3p0-config>

注意:配置文件的 的名字要和DataSource ds = new ComboPooledDataSource("helloc3p0");要傳入的參數(shù)一致震叮。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市浪慌,隨后出現(xiàn)的幾起案子冤荆,更是在濱河造成了極大的恐慌,老刑警劉巖权纤,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钓简,死亡現(xiàn)場離奇詭異,居然都是意外死亡汹想,警方通過查閱死者的電腦和手機外邓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來古掏,“玉大人损话,你說我怎么就攤上這事〔弁伲” “怎么了丧枪?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長庞萍。 經(jīng)常有香客問我拧烦,道長,這世上最難降的妖魔是什么钝计? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任恋博,我火速辦了婚禮,結(jié)果婚禮上私恬,老公的妹妹穿的比我還像新娘债沮。我一直安慰自己,他們只是感情好本鸣,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布疫衩。 她就那樣靜靜地躺著,像睡著了一般永高。 火紅的嫁衣襯著肌膚如雪隧土。 梳的紋絲不亂的頭發(fā)上提针,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音曹傀,去河邊找鬼辐脖。 笑死,一個胖子當(dāng)著我的面吹牛皆愉,可吹牛的內(nèi)容都是我干的嗜价。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼幕庐,長吁一口氣:“原來是場噩夢啊……” “哼久锥!你這毒婦竟也來了惰聂?” 一聲冷哼從身側(cè)響起听诸,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎痕檬,沒想到半個月后冤寿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歹苦,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年督怜,在試婚紗的時候發(fā)現(xiàn)自己被綠了殴瘦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡号杠,死狀恐怖蚪腋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情姨蟋,我是刑警寧澤屉凯,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站眼溶,受9級特大地震影響神得,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜偷仿,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宵蕉。 院中可真熱鬧酝静,春花似錦、人聲如沸羡玛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稼稿。三九已至薄榛,卻和暖如春讳窟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背敞恋。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工丽啡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人硬猫。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓补箍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親啸蜜。 傳聞我的和親對象是個殘疾皇子坑雅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容