java資料庫連線池dbcp的使用

業餘草發表於2014-07-16

近年來,隨著Internet/Intranet建網技術的飛速發展和在世界範圍內的迅速普及,計算機

  應用程式已從傳統的桌面應用轉到Web應用。基於B/S(Browser/Server)架構的3層開發模式逐漸取代C/S(Client/Server)架構的開發模式,成為開發企業級應用和電子商務普遍採用的技術。

在Java語言中,JDBC(Java DataBase Connection)是應用程式與資料庫溝通的橋樑,

  即Java語言通過JDBC技術訪問資料庫。JDBC是一種“開放”的方案,它為資料庫應用開發人員﹑資料庫前臺工具開發人員提供了一種標準的應用程式設計介面,使開發人員可以用純Java語言編寫完整的資料庫應用程式。JDBC提供兩種API,分別是面向開發人員的API和麵向底層的JDBC驅動程式API,底層主要通過直接的JDBC驅動和JDBC-ODBC橋驅動實現與資料庫的連線。

  一般來說,Java應用程式訪問資料庫的過程是:

  ①裝載資料庫驅動程式;

  ②通過JDBC建立資料庫連線;

  ③訪問資料庫,執行SQL語句;

  ④斷開資料庫連線。

JDBC作為一種資料庫訪問技術,具有簡單易用的優點。但使用這種模式進行Web應用
  程式開發,存在很多問題:首先,每一次Web請求都要建立一次資料庫連線。建立連線是一個費時的活動,每次都得花費0.05s~1s的時間,而且系統還要分配記憶體資源。這個時間對於一次或幾次資料庫操作,或許感覺不出系統有多大的開銷。可是對於現在的Web應用,尤其是大型電子商務網站,同時有幾百人甚至幾千人線上是很正常的事。在這種情況下,頻繁的進行資料庫連線操作勢必佔用很多的系統資源,網站的響應速度必定下降,嚴重的甚至會造成伺服器的崩潰。不是危言聳聽,這就是制約某些電子商務網站發展的技術瓶頸問題。其次,對於每一次資料庫連線,使用完後都得斷開。否則,如果程式出現異常而未能關閉,將會導致資料庫系統中的記憶體洩漏,最終將不得不重啟資料庫。還有,這種開發不能控制被建立的連線物件數,系統資源會被毫無顧及的分配出去,如連線過多,也可能導致記憶體洩漏,伺服器崩潰。

由上面的分析可以看出,問題的根源就在於對資料庫連線資源的低效管理。我們知道,

  對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配﹑釋放所造成的問題。為解決上述問題,可以採用資料庫連線池技術。資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連線,當需要建立資料庫連線時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。我們可以通過設定連線池最大連線數來防止系統無盡的與資料庫連線。更為重要的是我們可以通過連線池的管理機制監視資料庫的連線的數量﹑使用情況,為系統開發﹑測試及效能調整提供依據。
dbcp資料庫連線池程式碼使用如下:

package util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.log4j.Logger;

/**
 * Description: 資料庫連線池類
 * @filename DataSourceFactory.java 
 * @date 2013年8月21日 19:47:21
 * @author Herman.Xiong
 * @version 1.0
 * Copyright (c) 2013 Company,Inc. All Rights Reserved.
 */
public class DataSourceFactory {
	private static Logger log = Logger.getLogger(DataSourceFactory.class);
	private static BasicDataSource bs = null;
	public static String driver,url,userName,password;
	
	/**
	 * 建立資料來源
	 * @return
	 */
	public static BasicDataSource getDataSource() throws Exception{
		if(bs==null){
			log.info("資料庫連線資訊:[driver:"+driver+",url:"+url+",userName:"+userName+",password:"+password+"]");
			bs = new BasicDataSource();
			bs.setDriverClassName(driver);
			bs.setUrl(url);
			bs.setUsername(userName);
			bs.setPassword(password);
			bs.setMaxActive(200);//設定最大併發數
			bs.setInitialSize(30);//資料庫初始化時,建立的連線個數
			bs.setMinIdle(50);//最小空閒連線數
			bs.setMaxIdle(200);//資料庫最大連線數
			bs.setMaxWait(1000);
			bs.setMinEvictableIdleTimeMillis(60*1000);//空閒連線60秒中後釋放
			bs.setTimeBetweenEvictionRunsMillis(5*60*1000);//5分鐘檢測一次是否有死掉的執行緒
			bs.setTestOnBorrow(true);
		}
		return bs;
	}
	
	/**
	 * 釋放資料來源
	 */
	public static void shutDownDataSource() throws Exception{
		if(bs!=null){
			bs.close();
		}
	}
	
	/**
	 * 獲取資料庫連線
	 * @return
	 */
	public static Connection getConnection(){
		Connection con=null;
		try {
			if(bs!=null){
				con=bs.getConnection();
			}else{
				con=getDataSource().getConnection();
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return con;
	}
	
	/**
	 * 關閉連線
	 */
	public static void closeCon(ResultSet rs,PreparedStatement ps,Connection con){
		if(rs!=null){
			try {
				rs.close();
			} catch (Exception e) {
				log.error("關閉結果集ResultSet異常!"+e.getMessage(), e);
			}
		}
		if(ps!=null){
			try {
				ps.close();
			} catch (Exception e) {
				log.error("預編譯SQL語句物件PreparedStatement關閉異常!"+e.getMessage(), e);
			}
		}
		if(con!=null){
			try {
				con.close();
			} catch (Exception e) {
				log.error("關閉連線物件Connection異常!"+e.getMessage(), e);
			}
		}
	}
}


相關文章