Java 數(shù)據(jù)庫連接池筆記

JDBC

Java 數(shù)據(jù)庫連接(Java Database Connectivity,簡稱JDBC)是 Java 語言中用來規(guī)范客戶端程序如何來訪問數(shù)據(jù)庫的應(yīng)用程序接口,提供了諸如查詢和更新數(shù)據(jù)庫中數(shù)據(jù)的方法。

JDBC 的創(chuàng)建

使用 JDBC 訪問數(shù)據(jù)庫的流程:

  1. 加載 JDBC 驅(qū)動(dòng)
  2. 連接數(shù)據(jù)庫
  3. 執(zhí)行 SQL 查詢
  4. 從結(jié)果集中提取數(shù)據(jù)
  5. 處理結(jié)果集
  6. 清理環(huán)境,關(guān)閉所有的數(shù)據(jù)庫資源,釋放內(nèi)存

關(guān)于 JDBC 更詳細(xì)的介紹與使用:Java-MySQL連接

JDBC 的缺點(diǎn)

熟悉 JDBC 編程的,我們知道它存在很多缺點(diǎn),如:

  1. 數(shù)據(jù)庫連接,使用時(shí)創(chuàng)建,不使用立即釋放,對數(shù)據(jù)庫進(jìn)行頻繁連接開啟和關(guān)閉,造成數(shù)據(jù)庫資源浪費(fèi),影響了數(shù)據(jù)庫的性能。
  2. 將 sql 語句硬編碼到j(luò)ava代碼中,如果 sql 語句的修改,需要重新編譯java代碼,不利于系統(tǒng)的維護(hù)
  3. 向 preparedStatement 中設(shè)置參數(shù),對占位符位置和參數(shù)值,硬編碼在代碼中,不利于系統(tǒng)的維護(hù)。
  4. 從 resultSet 中遍歷結(jié)果集數(shù)據(jù)時(shí),存在硬編碼,將獲取表的字段進(jìn)行硬編碼,不利于系統(tǒng)的維護(hù)。

針對上述缺點(diǎn),我們對應(yīng)的解決方案:

  • 問題1:使用數(shù)據(jù)庫的連接池管理數(shù)據(jù)庫的連接。
  • 問題2:將 sql 語句配置到 xml 配置文件中,即使 sql 變化,不需要對 java 進(jìn)行重新編譯
  • 問題3:將 sql 語句和參數(shù)值配置到 xml 中
  • 問題4:將查詢的結(jié)果自動(dòng)的映射的 java 的對象

總的來說,我們主要會(huì)采用數(shù)據(jù)庫連接池解決數(shù)據(jù)庫頻繁鏈接與釋放問題,采用配置文件解決 sql 語句硬編碼問題。

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

連接池技術(shù)的核心思想是:連接復(fù)用,通過建立一個(gè)數(shù)據(jù)庫連接池以及一套連接使用、分配、管理策略,使得該連接池中的連接可以得到高效、安全的復(fù)用,避免了數(shù)據(jù)庫連接頻繁建立、關(guān)閉的開銷。另外,由于對 JDBC 中的原始連接進(jìn)行了封裝,從而方便了數(shù)據(jù)庫應(yīng)用對于連接的使用(特別是對于事務(wù)處理),提高了開發(fā)效率,也正是因?yàn)檫@個(gè)封裝層的存在,隔離了應(yīng)用的本身的處理邏輯和具體數(shù)據(jù)庫訪問邏輯,使應(yīng)用本身的復(fù)用成為可能。

連接池的操作:

  1. 建立數(shù)據(jù)庫連接池對象(服務(wù)器啟動(dòng))。
  2. 按照事先指定的參數(shù)創(chuàng)建初始數(shù)量的數(shù)據(jù)庫連接(即:空閑連接數(shù))。
  3. 對于一個(gè)數(shù)據(jù)庫訪問請求,直接從連接池中得到一個(gè)連接。如果數(shù)據(jù)庫連接池對象中沒有空閑的連接,且連接數(shù)沒有達(dá)到最大(即:最大活躍連接數(shù)),創(chuàng)建一個(gè)新的數(shù)據(jù)庫連接。
  4. 存取數(shù)據(jù)庫。
  5. 關(guān)閉數(shù)據(jù)庫,釋放所有數(shù)據(jù)庫連接(此時(shí)的關(guān)閉數(shù)據(jù)庫連接,并非真正關(guān)閉,而是將其放入空閑隊(duì)列中。如實(shí)際空閑連接數(shù)大于初始空閑連接數(shù)則釋放連接)。
  6. 釋放數(shù)據(jù)庫連接池對象(服務(wù)器停止、維護(hù)期間,釋放數(shù)據(jù)庫連接池對象,并釋放所有連接)。

自定義數(shù)據(jù)庫連接池

大致了解了數(shù)據(jù)庫連接池的原理與創(chuàng)建方法,我們可以自己編寫一個(gè)數(shù)據(jù)庫連接池,而編寫連接池需實(shí)現(xiàn)javax.sql.DataSource接口。DataSource接口中定義了兩個(gè)重載的getConnection方法:

  Connection.getConnection() 

  Connection.getConnection(String username, String password) 

自定義一個(gè)類,實(shí)現(xiàn)DataSource接口,并實(shí)現(xiàn)連接池功能的步驟:

  1. 在自定義類的構(gòu)造函數(shù)中批量創(chuàng)建Connection,并把創(chuàng)建的連接保存到一個(gè)集合對象中(LinkedList)。
  2. 在自定義類中實(shí)現(xiàn)Connection.getConnection方法,讓getConnection方法每次調(diào)用時(shí),從集合對象中取出一個(gè)Connection返回給用戶。
  3. 當(dāng)用戶使用完Connection,不能調(diào)用Connection.close()方法,而要使用連接池提供關(guān)閉方法,即將Connection放回到連接池之中(把Connection存入集合對象中)。

注:Connection對象應(yīng)保證將自己返回到連接池的集合對象中,而不要把Connection還給數(shù)據(jù)庫。

實(shí)際編程時(shí)我們并不需要自己編寫連接數(shù)據(jù)庫代碼,有一些開源組織提供了數(shù)據(jù)庫連接池的實(shí)現(xiàn),我們只要會(huì)使用即可。在我實(shí)習(xí)的公司,主要使用以下兩種開源數(shù)據(jù)庫連接池:

  • C3P0 數(shù)據(jù)庫連接池
  • DBCP 數(shù)據(jù)庫連接池

為此,就這兩種數(shù)據(jù)庫連接池,我做一簡單的介紹。

C3P0 數(shù)據(jù)庫連接池

C3P0 是一個(gè)開源的 JDBC 連接池,它實(shí)現(xiàn)了數(shù)據(jù)源和 JNDI 綁定,支持 JDBC3 規(guī)范和 JDBC2 的標(biāo)準(zhǔn)擴(kuò)展。目前使用它的開源項(xiàng)目有Hibernate,Spring 等。

C3P0 所需 JAR 包: c3p0-0.9.2.1.jar 和 mchange-commons-java-0.2.3.4.jar

配置文件常用的屬性:

####### c3p0 #######
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test
c3p0.user=xxxx
c3p0.password=xxxxx

c3p0.initialPoolSize=10 //初始化連接數(shù)
c3p0.minPoolSize=10 //最大連接數(shù)
c3p0.maxPoolSize=30 //最小連接數(shù)
c3p0.maxIdleTime=30 //最大空閑時(shí)間 => 這就是為什么C3P0有自動(dòng)回收的原因
c3p0.acquireIncrement=5 //新增連接數(shù)

當(dāng)創(chuàng)建連接池時(shí),一次性創(chuàng)建initialPoolSize 個(gè)連接,當(dāng)連接使用完一次性創(chuàng)建 acquireIncrement 個(gè)連接,連接最大數(shù)量 maxPoolSize ,當(dāng)連接池連接數(shù)量大于 minPoolSize ,經(jīng)過 maxIdleTime 連接沒有使用, 該連接將被釋放。

C3P0 連接創(chuàng)建方式主要分為:配置文件形式和硬編碼形式,這點(diǎn)和 DBCP 數(shù)據(jù)庫連接池非常相似,唯一不同的就是配置文件命名規(guī)范不同,C3P0 配置文件必須命名為 c3p0-config.xml 或 c3p0-config.properties ,并且放在 src 目錄下,而 DBCP 沒有這樣的要求。

DBCP 數(shù)據(jù)庫連接池

DBCP(DataBase connection pool), 數(shù)據(jù)庫連接池。是 apache 上的一個(gè) java 連接池項(xiàng)目,也是 tomcat 默認(rèn)使用的連接池組件。

DBCP 需要3個(gè)包:common-dbcp.jar,common-pool.jar,common-collections.jar

配置文件常用的屬性:

####### dbcp #######
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=xxxx
password=xxxxx

initialSize=10
# maxActive=10  // dbcp2中已將MaxActive設(shè)置為MaxTotal
maxTotal=30  // 可以在這個(gè)池中同時(shí)被分配的有效連接數(shù)的最大值,如設(shè)置為負(fù)數(shù),則不限制
maxIdle=10  // 可以在池中保持空閑的最大連接數(shù),超出設(shè)置值之外的空閑連接將被回收,如設(shè)置為負(fù)數(shù),則不限制
minIdle=5   // 可以在池中保持空閑的最小連接數(shù),超出設(shè)置值之外的空閑連接將被創(chuàng)建,如設(shè)置為0,則不創(chuàng)建

關(guān)于 C3P0 和 DBCP 配置文件更詳細(xì)的說明,請自行了解。Demo 可參見我的GitHub倉庫,后續(xù)會(huì)補(bǔ)充測試代碼。

C3P0 與 DBCP 區(qū)別

  1. C3P0 自動(dòng)回收空閑連接
  • 主要因?yàn)?maxIdleTime 屬性,當(dāng)連接池連接數(shù)量大于 minPoolSize ,經(jīng)過 maxIdleTime 連接沒有使用, 該連接將被釋放
  1. C3P0 擁有 3 種配置方法,DBCP 擁有 2 種配置方法
  2. 對數(shù)據(jù)連接的處理方式,C3P0 提供最大空閑時(shí)間,DBCP 提供最大連接數(shù)
  • 前者當(dāng)連接超過最大空閑連接時(shí)間時(shí),當(dāng)前連接就會(huì)被斷掉。DBCP 當(dāng)連接數(shù)超過最大連接數(shù)時(shí),所有連接都會(huì)被斷開。

參考鏈接

  1. 數(shù)據(jù)庫連接池的工作原理
  2. JDBC 進(jìn)階——連接池
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文包括傳統(tǒng)JDBC的缺點(diǎn)連接池原理自定義連接池開源數(shù)據(jù)庫連接池DBCP連接池C3P0連接池Tomcat內(nèi)置連接池...
    廖少少閱讀 16,938評論 0 37
  • 前言 數(shù)據(jù)庫連接池在Java數(shù)據(jù)庫相關(guān)中間件產(chǎn)品群中,應(yīng)該算是底層最基礎(chǔ)的一類產(chǎn)品,作為企業(yè)應(yīng)用開發(fā)必不可少的組件...
    許da廣閱讀 7,433評論 2 27
  • 最原始的數(shù)據(jù)庫連接就是我們打開一個(gè)連接,使用過后再關(guān)閉該鏈接來釋放資源。頻繁的新建打開再關(guān)閉連接對jvm和數(shù)據(jù)庫都...
    野柳閱讀 6,584評論 1 11
  • 以一個(gè)xx.png圖片來說內(nèi)部的結(jié)構(gòu)如下: 一開始是.png 后面緊跟 寬 高 然后是數(shù)據(jù) 最后是圖片描述(拍攝時(shí)...
    劉書亞的天堂之路閱讀 1,843評論 2 2
  • 又到一周做自然筆記啦!這周的主題是……昆蟲! 恰巧就看到了小朋友養(yǎng)的蠶寶寶了,已處于“眠”時(shí)期的它們開始吐絲了哦⊙ ⊙
    db21dd77f543閱讀 415評論 0 2

友情鏈接更多精彩內(nèi)容