love fish大鵬一曰同風(fēng)起,扶搖直上九萬里

          常用鏈接

          統(tǒng)計(jì)

          積分與排名

          friends

          link

          最新評(píng)論

          Java jdbc數(shù)據(jù)庫連接池總結(jié)(轉(zhuǎn))

          1. 引言

            近年來,隨著Internet/Intranet建網(wǎng)技術(shù)的飛速發(fā)展和在世界范圍內(nèi)的迅速普及,計(jì)算機(jī)

            應(yīng)用程序已從傳統(tǒng)的桌面應(yīng)用轉(zhuǎn)到Web應(yīng)用。基于B/S(Browser/Server)架構(gòu)的3層開發(fā)模式逐漸取代C/S(Client/Server)架構(gòu)的開發(fā)模式,成為開發(fā)企業(yè)級(jí)應(yīng)用和電子商務(wù)普遍采用的技術(shù)。在Web應(yīng)用開發(fā)的早期,主要使用的技術(shù)是CGIASPPHP等。之后,Sun公司推出了基于Java語言的Servlet+Jsp+JavaBean技術(shù)。相比傳統(tǒng)的開發(fā)技術(shù),它具有跨平臺(tái)﹑安全﹑有效﹑可移植等特性,這使其更便于使用和開發(fā)。

            Java應(yīng)用程序訪問數(shù)據(jù)庫的基本原理

            在Java語言中,JDBC(Java DataBase Connection)是應(yīng)用程序與數(shù)據(jù)庫溝通的橋梁,

            即Java語言通過JDBC技術(shù)訪問數(shù)據(jù)庫。JDBC是一種“開放”的方案,它為數(shù)據(jù)庫應(yīng)用開發(fā)人員﹑數(shù)據(jù)庫前臺(tái)工具開發(fā)人員提供了一種標(biāo)準(zhǔn)的應(yīng)用程序設(shè)計(jì)接口,使開發(fā)人員可以用純Java語言編寫完整的數(shù)據(jù)庫應(yīng)用程序。JDBC提供兩種API,分別是面向開發(fā)人員的API和面向底層的JDBC驅(qū)動(dòng)程序API,底層主要通過直接的JDBC驅(qū)動(dòng)和JDBC-ODBC橋驅(qū)動(dòng)實(shí)現(xiàn)與數(shù)據(jù)庫的連接。

            一般來說,Java應(yīng)用程序訪問數(shù)據(jù)庫的過程(如圖1所示)是:

            ①裝載數(shù)據(jù)庫驅(qū)動(dòng)程序;

            ②通過JDBC建立數(shù)據(jù)庫連接;

            ③訪問數(shù)據(jù)庫,執(zhí)行SQL語句;

            ④斷開數(shù)據(jù)庫連接。


          圖1 Java數(shù)據(jù)庫訪問機(jī)制
            JDBC作為一種數(shù)據(jù)庫訪問技術(shù),具有簡單易用的優(yōu)點(diǎn)。但使用這種模式進(jìn)行Web應(yīng)用
            程序開發(fā),存在很多問題:首先,每一次Web請(qǐng)求都要建立一次數(shù)據(jù)庫連接。建立連接是一個(gè)費(fèi)時(shí)的活動(dòng),每次都得花費(fèi)0.05s~1s的時(shí)間,而且系統(tǒng)還要分配內(nèi)存資源。這個(gè)時(shí)間對(duì)于一次或幾次數(shù)據(jù)庫操作,或許感覺不出系統(tǒng)有多大的開銷。可是對(duì)于現(xiàn)在的Web應(yīng)用,尤其是大型電子商務(wù)網(wǎng)站,同時(shí)有幾百人甚至幾千人在線是很正常的事。在這種情況下,頻繁的進(jìn)行數(shù)據(jù)庫連接操作勢(shì)必占用很多的系統(tǒng)資源,網(wǎng)站的響應(yīng)速度必定下降,嚴(yán)重的甚至?xí)斐煞?wù)器的崩潰。不是危言聳聽,這就是制約某些電子商務(wù)網(wǎng)站發(fā)展的技術(shù)瓶頸問題。其次,對(duì)于每一次數(shù)據(jù)庫連接,使用完后都得斷開。否則,如果程序出現(xiàn)異常而未能關(guān)閉,將會(huì)導(dǎo)致數(shù)據(jù)庫系統(tǒng)中的內(nèi)存泄漏,最終將不得不重啟數(shù)據(jù)庫。還有,這種開發(fā)不能控制被創(chuàng)建的連接對(duì)象數(shù),系統(tǒng)資源會(huì)被毫無顧及的分配出去,如連接過多,也可能導(dǎo)致內(nèi)存泄漏,服務(wù)器崩潰。
          ?
            數(shù)據(jù)庫連接池(connection pool)的工作原理
            1、基本概念及原理
          由上面的分析可以看出,問題的根源就在于對(duì)數(shù)據(jù)庫連接資源的低效管理。我們知道,
            對(duì)于共享資源,有一個(gè)很著名的設(shè)計(jì)模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配﹑釋放所造成的問題。為解決上述問題,可以采用數(shù)據(jù)庫連接池技術(shù)。數(shù)據(jù)庫連接池的基本思想就是為數(shù)據(jù)庫連接建立一個(gè)“緩沖池”。預(yù)先在緩沖池中放入一定數(shù)量的連接,當(dāng)需要建立數(shù)據(jù)庫連接時(shí),只需從“緩沖池”中取出一個(gè),使用完畢之后再放回去。我們可以通過設(shè)定連接池最大連接數(shù)來防止系統(tǒng)無盡的與數(shù)據(jù)庫連接。更為重要的是我們可以通過連接池的管理機(jī)制監(jiān)視數(shù)據(jù)庫的連接的數(shù)量﹑使用情況,為系統(tǒng)開發(fā)﹑測試及性能調(diào)整提供依據(jù)。連接池的基本工作原理見下圖2。

          圖2 連接池的基本工作原理
            2、服務(wù)器自帶的連接池
            JDBC的API中沒有提供連接池的方法。一些大型的WEB應(yīng)用服務(wù)器如BEA的WebLogic和IBM的WebSphere等提供了連接池的機(jī)制,但是必須有其第三方的專用類方法支持連接池的用法。
            連接池關(guān)鍵問題分析
            1、并發(fā)問題
            為了使連接管理服務(wù)具有最大的通用性,必須考慮多線程環(huán)境,即并發(fā)問題。這個(gè)問題相對(duì)比較好解決,因?yàn)?a target="_blank">Java語言自身提供了對(duì)并發(fā)管理的支持,使用synchronized關(guān)鍵字即可確保線程是同步的。使用方法為直接在類方法前面加上synchronized關(guān)鍵字,如:
          public synchronized Connection getConnection()
            2、多數(shù)據(jù)庫服務(wù)器和多用戶
            對(duì)于大型的企業(yè)級(jí)應(yīng)用,常常需要同時(shí)連接不同的數(shù)據(jù)庫(如連接OracleSybase)。如何連接不同的數(shù)據(jù)庫呢?我們采用的策略是:設(shè)計(jì)一個(gè)符合單例模式的連接池管理類,在連接池管理類的唯一實(shí)例被創(chuàng)建時(shí)讀取一個(gè)資源文件,其中資源文件中存放著多個(gè)數(shù)據(jù)庫的url地址(<poolName.url>)﹑用戶名(<poolName.user>)﹑密碼(<poolName.password>)等信息。如tx.url=192.168.1.123:5000/tx_it,tx.user=cyl,tx.password=123456。根據(jù)資源文件提供的信息,創(chuàng)建多個(gè)連接池類的實(shí)例,每一個(gè)實(shí)例都是一個(gè)特定數(shù)據(jù)庫的連接池。連接池管理類實(shí)例為每個(gè)連接池實(shí)例取一個(gè)名字,通過不同的名字來管理不同的連接池。
            對(duì)于同一個(gè)數(shù)據(jù)庫有多個(gè)用戶使用不同的名稱和密碼訪問的情況,也可以通過資源文件處理,即在資源文件中設(shè)置多個(gè)具有相同url地址,但具有不同用戶名和密碼的數(shù)據(jù)庫連接信息。
            3、事務(wù)處理
            我們知道,事務(wù)具有原子性,此時(shí)要求對(duì)數(shù)據(jù)庫的操作符合“ALL-ALL-NOTHING”原則,即對(duì)于一組SQL語句要么全做,要么全不做。
          Java語言中,Connection類本身提供了對(duì)事務(wù)的支持,可以通過設(shè)置Connection的AutoCommit屬性為false,然后顯式的調(diào)用commit或rollback方法來實(shí)現(xiàn)。但要高效的進(jìn)行Connection復(fù)用,就必須提供相應(yīng)的事務(wù)支持機(jī)制。可采用每一個(gè)事務(wù)獨(dú)占一個(gè)連接來實(shí)現(xiàn),這種方法可以大大降低事務(wù)管理的復(fù)雜性。
            4、連接池的分配與釋放
            連接池的分配與釋放,對(duì)系統(tǒng)的性能有很大的影響。合理的分配與釋放,可以提高連接的復(fù)用度,從而降低建立新連接的開銷,同時(shí)還可以加快用戶的訪問速度。
            對(duì)于連接的管理可使用空閑池。即把已經(jīng)創(chuàng)建但尚未分配出去的連接按創(chuàng)建時(shí)間存放到一個(gè)空閑池中。每當(dāng)用戶請(qǐng)求一個(gè)連接時(shí),系統(tǒng)首先檢查空閑池內(nèi)有沒有空閑連接。如果有就把建立時(shí)間最長(通過容器的順序存放實(shí)現(xiàn))的那個(gè)連接分配給他(實(shí)際是先做連接是否有效的判斷,如果可用就分配給用戶,如不可用就把這個(gè)連接從空閑池刪掉,重新檢測空閑池是否還有連接);如果沒有則檢查當(dāng)前所開連接池是否達(dá)到連接池所允許的最大連接數(shù)(maxConn),如果沒有達(dá)到,就新建一個(gè)連接,如果已經(jīng)達(dá)到,就等待一定的時(shí)間(timeout)。如果在等待的時(shí)間內(nèi)有連接被釋放出來就可以把這個(gè)連接分配給等待的用戶,如果等待時(shí)間超過預(yù)定時(shí)間timeout,則返回空值(null)。系統(tǒng)對(duì)已經(jīng)分配出去正在使用的連接只做計(jì)數(shù),當(dāng)使用完后再返還給空閑池。對(duì)于空閑連接的狀態(tài),可開辟專門的線程定時(shí)檢測,這樣會(huì)花費(fèi)一定的系統(tǒng)開銷,但可以保證較快的響應(yīng)速度。也可采取不開辟專門線程,只是在分配前檢測的方法。
            5、連接池的配置與維護(hù)
            連接池中到底應(yīng)該放置多少連接,才能使系統(tǒng)的性能最佳?系統(tǒng)可采取設(shè)置最小連接數(shù)(minConn)和最大連接數(shù)(maxConn)來控制連接池中的連接。最小連接數(shù)是系統(tǒng)啟動(dòng)時(shí)連接池所創(chuàng)建的連接數(shù)。如果創(chuàng)建過多,則系統(tǒng)啟動(dòng)就慢,但創(chuàng)建后系統(tǒng)的響應(yīng)速度會(huì)很快;如果創(chuàng)建過少,則系統(tǒng)啟動(dòng)的很快,響應(yīng)起來卻慢。這樣,可以在開發(fā)時(shí),設(shè)置較小的最小連接數(shù),開發(fā)起來會(huì)快,而在系統(tǒng)實(shí)際使用時(shí)設(shè)置較大的,因?yàn)檫@樣對(duì)訪問客戶來說速度會(huì)快些。最大連接數(shù)是連接池中允許連接的最大數(shù)目,具體設(shè)置多少,要看系統(tǒng)的訪問量,可通過反復(fù)測試,找到最佳點(diǎn)。
            如何確保連接池中的最小連接數(shù)呢?有動(dòng)態(tài)和靜態(tài)兩種策略。動(dòng)態(tài)即每隔一定時(shí)間就對(duì)連接池進(jìn)行檢測,如果發(fā)現(xiàn)連接數(shù)量小于最小連接數(shù),則補(bǔ)充相應(yīng)數(shù)量的新連接,以保證連接池的正常運(yùn)轉(zhuǎn)。靜態(tài)是發(fā)現(xiàn)空閑連接不夠時(shí)再去檢查。
          連接池的實(shí)現(xiàn)
            1、連接池模型
            本文討論的連接池包括一個(gè)連接池類(DBConnectionPool)和一個(gè)連接池管理類(DBConnetionPoolManager)和一個(gè)配置文件操作類(ParseDSConfig)。連接池類是對(duì)某一數(shù)據(jù)庫所有連接的“緩沖池”,主要實(shí)現(xiàn)以下功能:①從連接池獲取或創(chuàng)建可用連接;②使用完畢之后,把連接返還給連接池;③在系統(tǒng)關(guān)閉前,斷開所有連接并釋放連接占用的系統(tǒng)資源;④還能夠處理無效連接(原來登記為可用的連接,由于某種原因不再可用,如超時(shí),通訊問題),并能夠限制連接池中的連接總數(shù)不低于某個(gè)預(yù)定值和不超過某個(gè)預(yù)定值。(5)當(dāng)多數(shù)據(jù)庫時(shí),且數(shù)據(jù)庫是動(dòng)態(tài)增加的話,將會(huì)加到配置文件中。
            連接池管理類是連接池類的外覆類(wrapper),符合單例模式,即系統(tǒng)中只能有一個(gè)連接池管理類的實(shí)例。其主要用于對(duì)多個(gè)連接池對(duì)象的管理,具有以下功能:①裝載并注冊(cè)特定數(shù)據(jù)庫的JDBC驅(qū)動(dòng)程序;②根據(jù)屬性文件給定的信息,創(chuàng)建連接池對(duì)象;③為方便管理多個(gè)連接池對(duì)象,為每一個(gè)連接池對(duì)象取一個(gè)名字,實(shí)現(xiàn)連接池名字與其實(shí)例之間的映射;④跟蹤客戶使用連接情況,以便需要是關(guān)閉連接釋放資源。連接池管理類的引入主要是為了方便對(duì)多個(gè)連接池的使用和管理,如系統(tǒng)需要連接不同的數(shù)據(jù)庫,或連接相同的數(shù)據(jù)庫但由于安全性問題,需要不同的用戶使用不同的名稱和密碼。
          ???????? 2、連接池實(shí)現(xiàn)(經(jīng)過本人改版,可以適用多數(shù)據(jù)庫類型的應(yīng)用以及一種數(shù)據(jù)庫類型多個(gè)數(shù)據(jù)庫且數(shù)據(jù)? 庫的數(shù)量可以動(dòng)態(tài)增加的應(yīng)用程序)
          ???????? 1),DBConnectionPool.java?? 數(shù)據(jù)庫連接池類
          ???????? 2),DBConnectionManager?.java?? 數(shù)據(jù)庫管理類
          ???????? 3),DSConfigBean?.java??????????????? 單個(gè)數(shù)據(jù)庫連接信息Bean
          ???????? 4),ParseDSConfig.java??????????????? 操作多(這個(gè)'多'包括不同的數(shù)據(jù)庫和同一種數(shù)據(jù)庫有多個(gè)數(shù)據(jù)庫)
          ??????????????????????????????????????????????????????????? 數(shù)據(jù) 配置文件xml
          ???????? 5),ds.config.xml?????????????????????????? 數(shù)據(jù)庫配置文件xml
          ???????? 原代碼如下:?
          ??????? DBConnectionPool.java??
          ??????? ----------------------------------------------------------
          ????? /**
          ?*?數(shù)據(jù)庫連接池類
          ?*/
          package com.chunkyo.db;
          import java.sql.Connection;
          import java.sql.DriverManager;
          import java.sql.SQLException;
          import java.util.ArrayList;
          import java.util.Iterator;
          import java.util.Timer;
          /**
          ?* @author chenyanlin
          ?*
          ?*/
          public class DBConnectionPool implements TimerListener {
          ?private Connection con=null;
          ?private int inUsed=0;??? //使用的連接數(shù)
          ?private ArrayList freeConnections = new ArrayList();//容器,空閑連接
          ?private int minConn;???? //最小連接數(shù)
          ?private int maxConn;???? //最大連接
          ?private String name;???? //連接池名字
          ?private String password; //密碼
          ?private String url;????? //數(shù)據(jù)庫連接地址
          ?private String driver;?? //驅(qū)動(dòng)
          ?private String user;???? //用戶名
          ?public Timer timer;????? //定時(shí)
          ?/**
          ? *
          ? */
          ?public DBConnectionPool() {
          ??// TODO Auto-generated constructor stub
          ?}
          ?/**
          ? * 創(chuàng)建連接池
          ? * @param driver
          ? * @param name
          ? * @param URL
          ? * @param user
          ? * @param password
          ? * @param maxConn
          ? */
          ?public DBConnectionPool(String name, String driver,String URL, String user, String password, int maxConn)
          ?{
          ??this.name=name;
          ??this.driver=driver;
          ??this.url=URL;
          ??this.user=user;
          ??this.password=password;
          ??this.maxConn=maxConn;
          ?}
          ?/**
          ? * 用完,釋放連接
          ? * @param con
          ? */
          ?public synchronized void freeConnection(Connection con)
          ?{
          ??this.freeConnections.add(con);//添加到空閑連接的末尾
          ??this.inUsed--;
          ?}
          ?/**
          ? * timeout? 根據(jù)timeout得到連接
          ? * @param timeout
          ? * @return
          ? */
          ?public synchronized Connection getConnection(long timeout)
          ?{
          ??Connection con=null;
          ??if(this.freeConnections.size()>0)
          ??{
          ???con=(Connection)this.freeConnections.get(0);
          ???if(con==null)con=getConnection(timeout); //繼續(xù)獲得連接
          ??}
          ??else
          ??{
          ???con=newConnection(); //新建連接
          ??}
          ??if(this.maxConn==0||this.maxConn<this.inUsed)
          ??{
          ???con=null;//達(dá)到最大連接數(shù),暫時(shí)不能獲得連接了。
          ??}
          ??if(con!=null)
          ??{
          ???this.inUsed++;
          ??}
          ??return con;
          ?}
          ?/**
          ? *
          ? * 從連接池里得到連接
          ? * @return
          ? */
          ?public synchronized Connection getConnection()
          ?{
          ??Connection con=null;
          ??if(this.freeConnections.size()>0)
          ??{
          ???con=(Connection)this.freeConnections.get(0);
          ???this.freeConnections.remove(0);//如果連接分配出去了,就從空閑連接里刪除
          ???if(con==null)con=getConnection(); //繼續(xù)獲得連接
          ??}
          ??else
          ??{
          ???con=newConnection(); //新建連接
          ??}
          ??if(this.maxConn==0||this.maxConn<this.inUsed)
          ??{
          ???con=null;//等待 超過最大連接時(shí)
          ??}
          ??if(con!=null)
          ??{
          ???this.inUsed++;
          ???System.out.println("得到 "+this.name+" 的連接,現(xiàn)有"+inUsed+"個(gè)連接在使用!");
          ??}
          ??return con;
          ?}
          ?/**
          ? *釋放全部連接
          ? *
          ? */
          ?public synchronized void release()
          ?{
          ??Iterator allConns=this.freeConnections.iterator();
          ??while(allConns.hasNext())
          ??{
          ???Connection con=(Connection)allConns.next();
          ???try
          ???{
          ????con.close();
          ???}
          ???catch(SQLException e)
          ???{
          ????e.printStackTrace();
          ???}
          ???
          ??}
          ??this.freeConnections.clear();
          ???
          ?}
          ?/**
          ? * 創(chuàng)建新連接
          ? * @return
          ? */
          ?private Connection newConnection()
          ?{
          ??try {
          ???Class.forName(driver);
          ???con=DriverManager.getConnection(url, user, password);
          ??} catch (ClassNotFoundException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ???System.out.println("sorry can't find db driver!");
          ??} catch (SQLException e1) {
          ???// TODO Auto-generated catch block
          ???e1.printStackTrace();
          ???System.out.println("sorry can't create Connection!");
          ??}
          ??return con;
          ??
          ?}
          ?/**
          ? * 定時(shí)處理函數(shù)
          ? */
          ?public synchronized void TimerEvent()
          ?{
          ???? //暫時(shí)還沒有實(shí)現(xiàn)以后會(huì)加上的
          ?}
          ?/**
          ? * @param args
          ? */
          ?public static void main(String[] args) {
          ??// TODO Auto-generated method stub
          ?}
          ?/**
          ? * @return the driver
          ? */
          ?public String getDriver() {
          ??return driver;
          ?}
          ?/**
          ? * @param driver the driver to set
          ? */
          ?public void setDriver(String driver) {
          ??this.driver = driver;
          ?}
          ?/**
          ? * @return the maxConn
          ? */
          ?public int getMaxConn() {
          ??return maxConn;
          ?}
          ?/**
          ? * @param maxConn the maxConn to set
          ? */
          ?public void setMaxConn(int maxConn) {
          ??this.maxConn = maxConn;
          ?}
          ?/**
          ? * @return the minConn
          ? */
          ?public int getMinConn() {
          ??return minConn;
          ?}
          ?/**
          ? * @param minConn the minConn to set
          ? */
          ?public void setMinConn(int minConn) {
          ??this.minConn = minConn;
          ?}
          ?/**
          ? * @return the name
          ? */
          ?public String getName() {
          ??return name;
          ?}
          ?/**
          ? * @param name the name to set
          ? */
          ?public void setName(String name) {
          ??this.name = name;
          ?}
          ?/**
          ? * @return the password
          ? */
          ?public String getPassword() {
          ??return password;
          ?}
          ?/**
          ? * @param password the password to set
          ? */
          ?public void setPassword(String password) {
          ??this.password = password;
          ?}
          ?/**
          ? * @return the url
          ? */
          ?public String getUrl() {
          ??return url;
          ?}
          ?/**
          ? * @param url the url to set
          ? */
          ?public void setUrl(String url) {
          ??this.url = url;
          ?}
          ?/**
          ? * @return the user
          ? */
          ?public String getUser() {
          ??return user;
          ?}
          ?/**
          ? * @param user the user to set
          ? */
          ?public void setUser(String user) {
          ??this.user = user;
          ?}
          }

          -------------------------------------------
          ?DBConnectionManager?.java
          ------------------------------------------
          /**
          ?*?數(shù)據(jù)庫連接池管理類
          ?*/
          package com.chunkyo.db;
          import java.sql.Connection;
          import java.util.ArrayList;
          import java.util.Enumeration;
          import java.util.HashMap;
          import java.util.Hashtable;
          import java.util.Iterator;
          import java.util.Properties;
          import java.util.Vector;
          /**
          ?* @author chenyanlin
          ?*
          ?*/
          public class DBConnectionManager {
          ?static private DBConnectionManager instance;//唯一數(shù)據(jù)庫連接池管理實(shí)例類
          ?static private int clients;???????????????? //客戶連接數(shù)
          ?private Vector drivers? = new Vector();//驅(qū)動(dòng)信息
          ?private Hashtable pools=new Hashtable();//連接池
          ?
          ?/**
          ? * 實(shí)例化管理類
          ? */
          ?public DBConnectionManager() {
          ??// TODO Auto-generated constructor stub
          ??this.init();
          ?}
          ?/**
          ? * 得到唯一實(shí)例管理類
          ? * @return
          ? */
          ?static synchronized public DBConnectionManager getInstance()
          ?{
          ??if(instance==null)
          ??{
          ???instance=new DBConnectionManager();
          ??}
          ??return instance;
          ??
          ?}
          ?/**
          ? * 釋放連接
          ? * @param name
          ? * @param con
          ? */
          ?public void freeConnection(String name, Connection con)
          ?{
          ??DBConnectionPool pool=(DBConnectionPool)pools.get(name);//根據(jù)關(guān)鍵名字得到連接池
          ??if(pool!=null)
          ??pool.freeConnection(con);//釋放連接
          ?}
          ?/**
          ? * 得到一個(gè)連接根據(jù)連接池的名字name
          ? * @param name
          ? * @return
          ? */
          ?public Connection getConnection(String name)
          ?{
          ??DBConnectionPool pool=null;
          ??Connection con=null;
          ??pool=(DBConnectionPool)pools.get(name);//從名字中獲取連接池
          ??con=pool.getConnection();//從選定的連接池中獲得連接
          ??if(con!=null)
          ??System.out.println("得到連接。。。");
          ??return con;
          ?}
          ?/**
          ? * 得到一個(gè)連接,根據(jù)連接池的名字和等待時(shí)間
          ? * @param name
          ? * @param time
          ? * @return
          ? */
          ?public Connection getConnection(String name, long timeout)
          ?{
          ??DBConnectionPool pool=null;
          ??Connection con=null;
          ??pool=(DBConnectionPool)pools.get(name);//從名字中獲取連接池
          ??con=pool.getConnection(timeout);//從選定的連接池中獲得連接
          ??System.out.println("得到連接。。。");
          ??return con;
          ?}
          ?/**
          ? * 釋放所有連接
          ? */
          ?public synchronized void release()
          ?{
          ??Enumeration allpools=pools.elements();
          ??while(allpools.hasMoreElements())
          ??{
          ???DBConnectionPool pool=(DBConnectionPool)allpools.nextElement();
          ???if(pool!=null)pool.release();
          ??}
          ??pools.clear();
          ?}
          ?/**
          ? * 創(chuàng)建連接池
          ? * @param props
          ? */
          ?private void createPools(DSConfigBean dsb)
          ?{
          ??DBConnectionPool dbpool=new DBConnectionPool();
          ??dbpool.setName(dsb.getName());
          ??dbpool.setDriver(dsb.getDriver());
          ??dbpool.setUrl(dsb.getUrl());
          ??dbpool.setUser(dsb.getUsername());
          ??dbpool.setPassword(dsb.getPassword());
          ??dbpool.setMaxConn(dsb.getMaxconn());
          ??System.out.println("ioio:"+dsb.getMaxconn());
          ??pools.put(dsb.getName(), dbpool);
          ?}
          ?/**
          ? * 初始化連接池的參數(shù)
          ? */
          ?private void init()
          ?{
          ??//加載驅(qū)動(dòng)程序
          ??this.loadDrivers();
          ??//創(chuàng)建連接池
          ??Iterator alldriver=drivers.iterator();
          ??while(alldriver.hasNext())
          ??{
          ???this.createPools((DSConfigBean)alldriver.next());
          ???System.out.println("創(chuàng)建連接池。。。");
          ???
          ??}
          ??System.out.println("創(chuàng)建連接池完畢。。。");
          ?}
          ?/**
          ? * 加載驅(qū)動(dòng)程序
          ? * @param props
          ? */
          ?private void loadDrivers()
          ?{
          ??ParseDSConfig pd=new ParseDSConfig();
          ?//讀取數(shù)據(jù)庫配置文件
          ??drivers=pd.readConfigInfo("ds.config.xml");
          ??System.out.println("加載驅(qū)動(dòng)程序。。。");
          ?}
          ?/**
          ? * @param args
          ? */
          ?public static void main(String[] args) {
          ??// TODO Auto-generated method stub
          ?}
          }
          ----------------------------------------
          DSConfigBean.java
          ----------------------------------------
          /**
          ?*?配置文件Bean類
          ?*/
          package com.chunkyo.db;
          /**
          ?* @author chenyanlin
          ?*
          ?*/
          public class DSConfigBean {
          ?private String type???? =""; //數(shù)據(jù)庫類型
          ?private String name???? =""; //連接池名字
          ?private String driver?? =""; //數(shù)據(jù)庫驅(qū)動(dòng)
          ?private String url????? =""; //數(shù)據(jù)庫url
          ?private String username =""; //用戶名
          ?private String password =""; //密碼
          ?private int maxconn? =0; //最大連接數(shù)
          ?/**
          ? *
          ? */
          ?public DSConfigBean() {
          ??// TODO Auto-generated constructor stub
          ?}
          ?/**
          ? * @param args
          ? */
          ?public static void main(String[] args) {
          ??// TODO Auto-generated method stub
          ?}
          ?/**
          ? * @return the driver
          ? */
          ?public String getDriver() {
          ??return driver;
          ?}
          ?/**
          ? * @param driver the driver to set
          ? */
          ?public void setDriver(String driver) {
          ??this.driver = driver;
          ?}
          ?/**
          ? * @return the maxconn
          ? */
          ?public int getMaxconn() {
          ??return maxconn;
          ?}
          ?/**
          ? * @param maxconn the maxconn to set
          ? */
          ?public void setMaxconn(int maxconn) {
          ??this.maxconn = maxconn;
          ?}
          ?/**
          ? * @return the name
          ? */
          ?public String getName() {
          ??return name;
          ?}
          ?/**
          ? * @param name the name to set
          ? */
          ?public void setName(String name) {
          ??this.name = name;
          ?}
          ?/**
          ? * @return the password
          ? */
          ?public String getPassword() {
          ??return password;
          ?}
          ?/**
          ? * @param password the password to set
          ? */
          ?public void setPassword(String password) {
          ??this.password = password;
          ?}
          ?/**
          ? * @return the type
          ? */
          ?public String getType() {
          ??return type;
          ?}
          ?/**
          ? * @param type the type to set
          ? */
          ?public void setType(String type) {
          ??this.type = type;
          ?}
          ?/**
          ? * @return the url
          ? */
          ?public String getUrl() {
          ??return url;
          ?}
          ?/**
          ? * @param url the url to set
          ? */
          ?public void setUrl(String url) {
          ??this.url = url;
          ?}
          ?/**
          ? * @return the username
          ? */
          ?public String getUsername() {
          ??return username;
          ?}
          ?/**
          ? * @param username the username to set
          ? */
          ?public void setUsername(String username) {
          ??this.username = username;
          ?}
          }
          -----------------------------------------------------
          ParseDSConfig.java
          -----------------------------------------------------
          /**
          ?*?操作配置文件類 讀? 寫 修改 刪除等操作
          ?*/
          package com.chunkyo.db;
          import java.io.FileInputStream;
          import java.io.FileNotFoundException;
          import java.io.FileOutputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.util.List;
          import java.util.Vector;
          import java.util.Iterator;
          import org.jdom.Document;
          import org.jdom.Element;
          import org.jdom.JDOMException;
          import org.jdom.input.SAXBuilder;
          import org.jdom.output.Format;
          import org.jdom.output.XMLOutputter;
          /**
          ?* @author chenyanlin
          ?*
          ?*/
          public class ParseDSConfig {
          ?/**
          ? * 構(gòu)造函數(shù)
          ? */
          ?public ParseDSConfig() {
          ??// TODO Auto-generated constructor stub
          ?}
          ?/**
          ? * 讀取xml配置文件
          ? * @param path
          ? * @return
          ? */
          ?public Vector readConfigInfo(String path)
          ?{
          ??String rpath=this.getClass().getResource("").getPath().substring(1)+path;
          ??Vector dsConfig=null;
          ??FileInputStream fi = null;
          ??try
          ??{
          ???fi=new FileInputStream(rpath);//讀取路徑文件
          ???dsConfig=new Vector();
          ???SAXBuilder sb=new SAXBuilder();
          ???Document doc=sb.build(fi);
          ???Element root=doc.getRootElement();
          ???List pools=root.getChildren();
          ???Element pool=null;
          ???Iterator allPool=pools.iterator();
          ???while(allPool.hasNext())
          ???{
          ????pool=(Element)allPool.next();
          ????DSConfigBean dscBean=new DSConfigBean();
          ????dscBean.setType(pool.getChild("type").getText());
          ????dscBean.setName(pool.getChild("name").getText());
          ????System.out.println(dscBean.getName());
          ????dscBean.setDriver(pool.getChild("driver").getText());
          ????dscBean.setUrl(pool.getChild("url").getText());
          ????dscBean.setUsername(pool.getChild("username").getText());
          ????dscBean.setPassword(pool.getChild("password").getText());
          ????dscBean.setMaxconn(Integer.parseInt(pool.getChild("maxconn").getText()));
          ????dsConfig.add(dscBean);
          ???}
          ???
          ??} catch (FileNotFoundException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??} catch (JDOMException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??} catch (IOException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??}
          ??
          ??finally
          ??{
          ???try {
          ????fi.close();
          ???} catch (IOException e) {
          ????// TODO Auto-generated catch block
          ????e.printStackTrace();
          ???}
          ??}
          ??
          ??return dsConfig;
          ?}
          /**
          ?*修改配置文件 沒時(shí)間寫 過段時(shí)間再貼上去 其實(shí)一樣的
          ?*/
          ?public void modifyConfigInfo(String path,DSConfigBean dsb) throws Exception
          ?{
          ??String rpath=this.getClass().getResource("").getPath().substring(1)+path;
          ??FileInputStream fi=null; //讀出
          ??FileOutputStream fo=null; //寫入
          ??
          ?}
          /**
          ?*增加配置文件
          ?*
          ?*/
          ?public void addConfigInfo(String path,DSConfigBean dsb)
          ?{
          ??String rpath=this.getClass().getResource("").getPath().substring(1)+path;
          ??FileInputStream fi=null;
          ??FileOutputStream fo=null;
          ??try
          ??{
          ???fi=new FileInputStream(rpath);//讀取xml流
          ???
          ???SAXBuilder sb=new SAXBuilder();
          ???
          ???Document doc=sb.build(fi); //得到xml
          ???Element root=doc.getRootElement();
          ???List pools=root.getChildren();//得到xml子樹
          ???
          ???Element newpool=new Element("pool"); //創(chuàng)建新連接池
          ???
          ???Element pooltype=new Element("type"); //設(shè)置連接池類型
          ???pooltype.setText(dsb.getType());
          ???newpool.addContent(pooltype);
          ???
          ???Element poolname=new Element("name");//設(shè)置連接池名字
          ???poolname.setText(dsb.getName());
          ???newpool.addContent(poolname);
          ???
          ???Element pooldriver=new Element("driver"); //設(shè)置連接池驅(qū)動(dòng)
          ???pooldriver.addContent(dsb.getDriver());
          ???newpool.addContent(pooldriver);
          ???
          ???Element poolurl=new Element("url");//設(shè)置連接池url
          ???poolurl.setText(dsb.getUrl());
          ???newpool.addContent(poolurl);
          ???
          ???Element poolusername=new Element("username");//設(shè)置連接池用戶名
          ???poolusername.setText(dsb.getUsername());
          ???newpool.addContent(poolusername);
          ???
          ???Element poolpassword=new Element("password");//設(shè)置連接池密碼
          ???poolpassword.setText(dsb.getPassword());
          ???newpool.addContent(poolpassword);
          ???
          ???Element poolmaxconn=new Element("maxconn");//設(shè)置連接池最大連接
          ???poolmaxconn.setText(String.valueOf(dsb.getMaxconn()));
          ???newpool.addContent(poolmaxconn);
          ???pools.add(newpool);//將child添加到root
          ???Format format = Format.getPrettyFormat();
          ????? format.setIndent("");
          ????? format.setEncoding("utf-8");
          ????? XMLOutputter outp = new XMLOutputter(format);
          ????? fo = new FileOutputStream(rpath);
          ????? outp.output(doc, fo);
          ??} catch (FileNotFoundException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??} catch (JDOMException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??} catch (IOException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??}
          ??finally
          ??{
          ???
          ??}
          ?}
          ?/**
          ? *刪除配置文件
          ? */
          ?public void delConfigInfo(String path,String name)
          ?{
          ??String rpath=this.getClass().getResource("").getPath().substring(1)+path;
          ??FileInputStream fi = null;
          ??FileOutputStream fo=null;
          ??try
          ??{
          ???fi=new FileInputStream(rpath);//讀取路徑文件
          ???SAXBuilder sb=new SAXBuilder();
          ???Document doc=sb.build(fi);
          ???Element root=doc.getRootElement();
          ???List pools=root.getChildren();
          ???Element pool=null;
          ???Iterator allPool=pools.iterator();
          ???while(allPool.hasNext())
          ???{
          ????pool=(Element)allPool.next();
          ????if(pool.getChild("name").getText().equals(name))
          ????{
          ?????pools.remove(pool);
          ?????break;
          ????}
          ???}
          ???Format format = Format.getPrettyFormat();
          ????? format.setIndent("");
          ????? format.setEncoding("utf-8");
          ????? XMLOutputter outp = new XMLOutputter(format);
          ????? fo = new FileOutputStream(rpath);
          ????? outp.output(doc, fo);
          ???
          ??} catch (FileNotFoundException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??} catch (JDOMException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??} catch (IOException e) {
          ???// TODO Auto-generated catch block
          ???e.printStackTrace();
          ??}
          ??
          ??finally
          ??{
          ???try {
          ????fi.close();
          ???} catch (IOException e) {
          ????// TODO Auto-generated catch block
          ????e.printStackTrace();
          ???}
          ??}
          ?}
          ?/**
          ? * @param args
          ? * @throws Exception
          ? */
          ?public static void main(String[] args) throws Exception {
          ??// TODO Auto-generated method stub
          ??ParseDSConfig pd=new ParseDSConfig();
          ??String path="ds.config.xml";
          ??pd.readConfigInfo(path);
          ??//pd.delConfigInfo(path, "tj012006");
          ??DSConfigBean dsb=new DSConfigBean();
          ??dsb.setType("oracle");
          ??dsb.setName("yyy004");
          ??dsb.setDriver("org.oracle.jdbc");
          ??dsb.setUrl("jdbc:oracle://localhost");
          ??dsb.setUsername("sa");
          ??dsb.setPassword("");
          ??dsb.setMaxconn(1000);
          ??pd.addConfigInfo(path, dsb);
          ??pd.delConfigInfo(path, "yyy001");
          ?}
          }

          --------------------------------------
          ds.config.xml?? 配置文件
          --------------------------------------


          <ds-config>
          <pool>
          <type>mysql</type>
          <name>user</name>
          <driver>com.mysql.jdbc.driver</driver>
          <url>jdbc:mysql://localhost:3306/user</url>
          <username>sa</username>
          <password>123456</password>
          <maxconn>100</maxconn>
          </pool>
          <pool>
          <type>mysql</type>
          <name>user2</name>
          <driver>com.mysql.jdbc.driver</driver>
          <url>jdbc:mysql://localhost:3306/user2</url>
          <username>sa</username>
          <password>1234</password>
          <maxconn>10</maxconn>
          </pool>
          <pool>
          <type>sql2000</type>
          <name>books</name>
          <driver>com.microsoft.sqlserver.driver</driver>
          <url>jdbc:sqlserver://localhost:1433/books:databasename=books</url>
          <username>sa</username>
          <password></password>
          <maxconn>100</maxconn>
          </pool>
          </ds-config>


          3. 連接池的使用
          ? 1。Connection的獲得和釋放
          ? DBConnectionManager?? connectionMan=DBConnectionManager?.getInstance();//得到唯一實(shí)例
          ?? //得到連接
          ?? String name="mysql";//從上下文得到你要訪問的數(shù)據(jù)庫的名字
          ?? Connection? con=connectionMan.getConnection(name);
          ? //使用
          ? 。。。。。。。
          ? // 使用完畢
          ?connectionMan.freeConnection(name,con);//釋放,但并未斷開連接
          ?2。數(shù)據(jù)庫連接的動(dòng)態(tài)增加和連接池的動(dòng)態(tài)增加
          ????? 1。調(diào)用xml操作增加類

          ??????2。重新實(shí)例華連接池管理池類

          posted on 2007-03-23 09:33 liaojiyong 閱讀(951) 評(píng)論(1)  編輯  收藏 所屬分類: DBMixture

          評(píng)論

          # re: Java jdbc數(shù)據(jù)庫連接池總結(jié)(轉(zhuǎn))[未登錄] 2010-12-17 02:20 小小

          你好,我使用了你上面的類 但是報(bào)錯(cuò)了java.lang.ClassNotFoundException: com.mysql.jdbc.driver
          但是我已經(jīng)把JAR包導(dǎo)入了啊
          請(qǐng)賜教
          我的郵箱是 hhayyok@163.com
          謝謝  回復(fù)  更多評(píng)論   

          主站蜘蛛池模板: 望奎县| 汶上县| 黄大仙区| 承德县| 鸡东县| 平罗县| 普陀区| 会泽县| 建湖县| 承德县| 进贤县| 福清市| 金溪县| 安徽省| 湖北省| 靖西县| 鹤壁市| 富阳市| 松原市| 温泉县| 共和县| 荥经县| 大渡口区| 临朐县| 武川县| 上林县| 集贤县| 景泰县| 墨竹工卡县| 长沙市| 和林格尔县| 荣成市| 滦南县| 高州市| 大同市| 龙州县| 外汇| 射阳县| 黄石市| 新宁县| 红安县|