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

1.JDBC介紹
 1.1 1.1 JDBC介紹

2.JDBC之API
 2.1 2.1 JDBC之API

3.JDBC例子
 3.1 3.1 前期準(zhǔn)備DBUtil
 3.2 3.2 DBUtil實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的CURD

4.JDBC之事務(wù)管理
 4.1 4.1 事務(wù)基礎(chǔ)概念
 4.2 4.2 事務(wù)實(shí)現(xiàn)轉(zhuǎn)賬功能

5.數(shù)據(jù)庫連接池
 5.1 數(shù)據(jù)庫連接池介紹
 5.2 JNDI訪問數(shù)據(jù)源
 5.3 開源數(shù)據(jù)庫連接池

一违崇、JDBC開發(fā)步驟

二坯沪、JDBC事務(wù)管理

Connection.setAutoCommit(boolean autoCommit) 修改自動(dòng)提交模式(默認(rèn)為true)
Connection.commit() 提交事務(wù)
Connection.rollback() 事務(wù)回滾

1榔袋、什么是事務(wù)

事務(wù)(Transaction):是并發(fā)控制的單元,是用戶定義的一個(gè)操作序列结洼。這些操作要么都做,要么都不做岛抄,是一個(gè)不可分割的工作單位璃诀。通過事務(wù),sql server 能將邏輯相關(guān)的一組操作綁定在一起谷暮,以便服務(wù)器 保持?jǐn)?shù)據(jù)的完整性蒿往。事務(wù)通常是以begin transaction開始,以commit或rollback結(jié)束湿弦。Commint表示提交瓤漏,即提交事務(wù)的所有操作。具體地說就是將事務(wù)中所有對(duì)數(shù)據(jù)的更新寫回到磁盤上的物理數(shù)據(jù)庫中去颊埃,事務(wù)正常結(jié)束蔬充。Rollback表示回滾,即在事務(wù)運(yùn)行的過程中發(fā)生了某種故障竟秫,事務(wù)不能繼續(xù)進(jìn)行娃惯,系統(tǒng)將事務(wù)中對(duì)數(shù)據(jù)庫的所有已完成的操作全部撤消,滾回到事務(wù)開始的狀態(tài)肥败。

事務(wù)的特性:
    1. 原子性(atomicity):事務(wù)是數(shù)據(jù)庫的邏輯工作單位趾浅,而且是必須是原子工作單位,對(duì)于其數(shù)據(jù)修改馒稍,要么全部執(zhí)行皿哨,要么全部不執(zhí)行。
    1. 一致性(consistency):事務(wù)在完成時(shí)纽谒,必須是所有的數(shù)據(jù)都保持一致狀態(tài)证膨。在相關(guān)數(shù)據(jù)庫中,所有規(guī)則都必須應(yīng)用于事務(wù)的修改鼓黔,以保持所有數(shù)據(jù)的完整性央勒。
    1. 隔離性(isolation):一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)所影響。
    1. 持久性(durability):一個(gè)事務(wù)一旦提交澳化,事物的操作便永久性的保存在DB中崔步。即使此時(shí)再執(zhí)行回滾操作也不能撤消所做的更改。
2缎谷、Java JDBC事務(wù)機(jī)制

JDBC對(duì)事務(wù)的支持體現(xiàn)在三個(gè)方面:

自動(dòng)提交模式(Auto-commit mode)

Connection提供了一個(gè)auto-commit的屬性來指定事務(wù)何時(shí)結(jié)束井濒。

  • a. 當(dāng)auto-commit為true時(shí)(默認(rèn)為true),當(dāng)每個(gè)獨(dú)立SQL操作的執(zhí)行完畢,事務(wù)立即自動(dòng)提交瑞你,也就是說每個(gè)SQL操作都是一個(gè)事務(wù)酪惭。一個(gè)獨(dú)立SQL操作什么時(shí)候算執(zhí)行完畢,JDBC規(guī)范是這樣規(guī)定的:

對(duì)數(shù)據(jù)操作語言(DML者甲,如insert,update,delete)和數(shù)據(jù)定義語言(如create,drop)春感,語句一執(zhí)行完就視為執(zhí)行完畢。

對(duì)select語句虏缸,當(dāng)與它關(guān)聯(lián)的ResultSet對(duì)象關(guān)閉時(shí)甥厦,視為執(zhí)行完畢。

對(duì)存儲(chǔ)過程或其他返回多個(gè)結(jié)果的語句寇钉,當(dāng)與它關(guān)聯(lián)的所有ResultSet對(duì)象全部關(guān)閉,所有update count(update,delete等語句操作影響的行數(shù))和output parameter(存儲(chǔ)過程的輸出參數(shù))都已經(jīng)獲取之后舶赔,視為執(zhí)行完畢岭粤。

  • b. 當(dāng)auto-commit為false時(shí)拒担,每個(gè)事務(wù)都必須顯示調(diào)用commit方法進(jìn)行提交,或者顯示調(diào)用rollback方法進(jìn)行回滾。auto-commit默認(rèn)為true形病。
例子
try {
        conn.setAutoCommit(false);  //將自動(dòng)提交設(shè)置為false
        ps.executeUpdate("修改SQL"); //執(zhí)行修改操作
        ps.executeQuery("查詢SQL");  //執(zhí)行查詢操作
        conn.commit();      //當(dāng)兩個(gè)操作成功后手動(dòng)提交
    } catch (Exception e) {
        conn.rollback();    //一旦其中一個(gè)操作出錯(cuò)都將回滾,使兩個(gè)操作都不成功
        e.printStackTrace();
    }

三侍匙、數(shù)據(jù)庫連接池

數(shù)據(jù)庫連接池的實(shí)現(xiàn)方法:

  • JNDI
  • 開源框架:DBCP迈喉、C3P0等
  • 公司用:持久層框架Mybatis

從數(shù)據(jù)庫連接池獲取的Connection是不需要關(guān)閉的,連接池將根據(jù)情況自動(dòng)關(guān)閉桶略。

1语淘、使用JNDI配置數(shù)據(jù)庫連接池

參考:JNDI 是什么 | Tomcat配置JNDI

JNDI(Java Naming and Directory Inteface)即Java名稱目錄接口。JNDI的作用:就是將資源引入到服務(wù)器中际歼』谭可以將JNDI當(dāng)成一個(gè)倉庫。將Java對(duì)象放入到JNDI中去鹅心。

JNDI提供了一種服務(wù)吕粗,這個(gè)服務(wù)可以將“名稱”和“資源”進(jìn)行綁定,然后程序員通過面向JNDI接口調(diào)用方法lookup可以查找到相關(guān)的資源旭愧。

基于JNDI的特性颅筋,用了JNDI之后建立數(shù)據(jù)庫連接池的做法:首先,在J2EE容器中配置JNDI參數(shù)输枯,定義一個(gè)數(shù)據(jù)源议泵,也就是JDBC引用參數(shù),給這個(gè)數(shù)據(jù)源設(shè)置一個(gè)名稱用押;然后肢簿,在程序中,通過數(shù)據(jù)源名稱引用數(shù)據(jù)源從而訪問后臺(tái)數(shù)據(jù)庫。

2池充、使用開源框架:以DBCP為例

DBCP(DatabaseConnection Pool)是一個(gè)依賴Jakarta commons-pool對(duì)象池機(jī)制的數(shù)據(jù)庫連接池桩引,Tomcat的數(shù)據(jù)源使用的就是DBCP。

DBCP使用Demo
1收夸、引入依賴
<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
</dependency>
2坑匠、配置文件(.properties)
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/db_qunar_fresh2017
jdbc.username=root  
jdbc.password=root  

#初始化連接
dataSource.initialSize=10  

#最大空閑連接
dataSource.maxIdle=20  

#最小空閑連接
dataSource.minIdle=5  

#最大連接數(shù)量
dataSource.maxActive=50  

#是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤
dataSource.logAbandoned=true  

#是否自動(dòng)回收超時(shí)連接
dataSource.removeAbandoned=true  

#超時(shí)時(shí)間(以秒數(shù)為單位)
dataSource.removeAbandonedTimeout=180  

#超時(shí)等待時(shí)間以毫秒為單位 6000毫秒/1000等于60秒
dataSource.maxWait=1000  
3、創(chuàng)建數(shù)據(jù)庫連接池卧惜、獲取連接(封裝工具類)
package com.qunar.fresh2017.db;

import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Copyright(C),2005-2017,Qunar.com
 * version    date      author
 * ──────────────────────────────────
 * 1.0       17-3-9   wanlong.ma
 * Description:DBCP連接池工具類
 * Others:
 * Function List:
 * History:
 */
public class DataSourceUtil {
    private static Logger logger = LoggerFactory.getLogger(DataSourceUtil.class);
    private static Properties properties = new Properties();

    private static DataSource dataSource;
    static {
        // 讀取配置文件
        try {
            properties.load(DataSourceUtil.class.getResourceAsStream("/dbcp.properties"));
        } catch (IOException e) {
            logger.error("讀取數(shù)據(jù)庫連接池配置文件失斃遄啤:/dbcp.properties",e);
        }
        // 創(chuàng)建數(shù)據(jù)庫連接池
        try {
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            logger.error("數(shù)據(jù)庫連接池創(chuàng)建失敗",e);
        }
    }

    /**
     * 獲取連接
     * @return
     */
    public static Connection getConnection(){
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            logger.error("從數(shù)據(jù)庫連接池中獲取連接失敗",e);
        }
        return connection;
    }
   
}
3、使用數(shù)據(jù)庫連接池是否需要關(guān)閉Connection

我們?cè)谄綍r(shí)項(xiàng)目中用到了數(shù)據(jù)庫連接池咽瓷,比如C3P0,DBCP,JNDI...
在使用結(jié)束的時(shí)候我們也要關(guān)閉連接设凹。
為什么呢。具體解釋如下:使用 C3P0 的話茅姜,也是 java.sql.Connection闪朱,只要是 JDBC 都是這個(gè)接口的對(duì)象!

使用完后必須 con.close() 掉 钻洒,使用連接池的話奋姿,執(zhí)行 con.close 并不會(huì)關(guān)閉與數(shù)據(jù)庫的 TCP 連接,而是將連接還回到池中去素标,如果不 close 掉的話称诗,這個(gè)連接將會(huì)一直被占用,直接連接池中的連接耗盡為止头遭。

也就是說:我們通過數(shù)據(jù)庫連接池獲取到的Connection是經(jīng)過連接池重寫后的Connection寓免,同為 java.sql.Connection,只是在關(guān)閉連接時(shí)计维,它重寫了colse方法再榄,使得Connection并不是斷開TCP連接,而是釋放享潜、還給連接池繼續(xù)分配困鸥。

至于是如何做到 con.close 并不是真正意義上的關(guān)閉連接?而是直接將連接還回到池中去剑按? 一般有兩種方式:

  • (1)使用裝飾器模式疾就,在裝飾器構(gòu)造中傳入一個(gè)真正的 Connection,這個(gè)裝飾器實(shí)現(xiàn) Connection艺蝴,使用構(gòu)造 傳入 Connection 委托重寫所有方法猬腰,并改寫 close 方法:

    public class ConnectionDecorator implements Connection {
    
      private Connection con = null;
    
      public ConnectionDecorator(Connection con) {
          this.con = con;
      }
    
      public void close() throws SQLException {
          // 重寫! 
      }
    
      public void commit() throws SQLException {
          this.con.commit();
      }
    
      public Statement createStatement() throws SQLException {
          return this.con.createStatement();
      }
    
      public Statement createStatement(int resultSetType, int resultSetConcurrency)
              throws SQLException {
          return this.con.createStatement(resultSetType, resultSetConcurrency);
      } 
     
       ......
    }
    

然后經(jīng)過連接池控制的 Connection 對(duì)象都使用該裝飾器進(jìn)行包裝

  • (2):動(dòng)態(tài)代理: 使用動(dòng)態(tài)代理重新實(shí)現(xiàn) close 方法猜敢,每個(gè)獲得 Connection 是一個(gè)代理后的對(duì)象姑荷。

一個(gè)完善的連接池盒延,其架構(gòu)設(shè)計(jì)非常復(fù)雜,Connection#close 問題就是連接池諸多設(shè)計(jì)難點(diǎn)當(dāng)中的一個(gè)鼠冕。

四添寺、補(bǔ)充問題

1、JDBC批處理

當(dāng)需要向數(shù)據(jù)庫發(fā)送一批SQL語句執(zhí)行時(shí)懈费,應(yīng)避免向數(shù)據(jù)庫一條條的發(fā)送執(zhí)行计露,而應(yīng)采用JDBC的批處理機(jī)制,以提升執(zhí)行效率憎乙。

2票罐、線程并發(fā)更新問題

例如:A、B同時(shí)給C轉(zhuǎn)賬(尤其是跨數(shù)據(jù)庫情況)泞边,如何保證各方的錢是正確的该押?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市阵谚,隨后出現(xiàn)的幾起案子沈善,更是在濱河造成了極大的恐慌,老刑警劉巖椭蹄,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異净赴,居然都是意外死亡绳矩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門玖翅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翼馆,“玉大人,你說我怎么就攤上這事金度∮γ模” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵猜极,是天一觀的道長中姜。 經(jīng)常有香客問我,道長跟伏,這世上最難降的妖魔是什么丢胚? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮受扳,結(jié)果婚禮上携龟,老公的妹妹穿的比我還像新娘。我一直安慰自己勘高,他們只是感情好峡蟋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布坟桅。 她就那樣靜靜地躺著,像睡著了一般蕊蝗。 火紅的嫁衣襯著肌膚如雪仅乓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天匿又,我揣著相機(jī)與錄音方灾,去河邊找鬼。 笑死碌更,一個(gè)胖子當(dāng)著我的面吹牛裕偿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播痛单,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嘿棘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了旭绒?” 一聲冷哼從身側(cè)響起鸟妙,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挥吵,沒想到半個(gè)月后重父,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忽匈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年房午,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丹允。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡郭厌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雕蔽,到底是詐尸還是另有隱情折柠,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布批狐,位于F島的核電站扇售,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏嚣艇。R本人自食惡果不足惜缘眶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望髓废。 院中可真熱鬧巷懈,春花似錦、人聲如沸慌洪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涌攻,卻和暖如春欧引,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恳谎。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國打工芝此, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人因痛。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓婚苹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸵膏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子膊升,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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

  • 一、事務(wù) 事務(wù)就是一個(gè)事情谭企,組成這個(gè)事情可能有多個(gè)單元廓译,要求這些單元,要么全都成功债查,要么全都不成功非区。在開發(fā)中,有事...
    野狗子嗷嗷嗷閱讀 2,805評(píng)論 0 6
  • 主要內(nèi)容 定義Spring的數(shù)據(jù)訪問支持 配置數(shù)據(jù)庫資源 使用Spring提供的JDBC模板 寫在前面:經(jīng)過上一篇...
    程序熊大閱讀 8,767評(píng)論 1 31
  • 本文包括傳統(tǒng)JDBC的缺點(diǎn)連接池原理自定義連接池開源數(shù)據(jù)庫連接池DBCP連接池C3P0連接池Tomcat內(nèi)置連接池...
    廖少少閱讀 16,749評(píng)論 0 37
  • 1.事務(wù) 1.1事務(wù)的四大特性(ACID) 原子性:事務(wù)中的所有操作要么全部執(zhí)行成功盹廷,要么執(zhí)行全部失敗征绸。 一致性:...
    joshul閱讀 434評(píng)論 0 1
  • 最原始的數(shù)據(jù)庫連接就是我們打開一個(gè)連接,使用過后再關(guān)閉該鏈接來釋放資源速和。頻繁的新建打開再關(guān)閉連接對(duì)jvm和數(shù)據(jù)庫都...
    野柳閱讀 6,366評(píng)論 1 11