Java jdbc資料庫連線池總結!
阿新 • • 發佈:2019-01-27
1. 引言
圖1 Java資料庫訪問機制 JDBC作為一種資料庫訪問技術,具有簡單易用的優點。但使用這種模式進行Web應用 程式開發,存在很多問題:首先,每一次Web請求都要建立一次資料庫連線。建立連線是一個費時的活動,每次都得花費0.05s~1s的時間,而且系統還要分配記憶體資源。這個時間對於一次或幾次資料庫操作,或許感覺不出系統有多大的開銷。可是對於現在的Web應用,尤其是大型電子商務 網站,同時有幾百人甚至幾千人線上是很正常的事。在這種情況下,頻繁的進行資料庫連線操作勢必佔用很多的系統資源,網站的響應速度必定下降,嚴重的甚至會造成伺服器的崩潰。不是危言聳聽,這就是制約某些電子商務網站發展的技術瓶頸問題。其次,對於每一次資料庫連線,使用完後都得斷開。否則,如果程式出現異常而未能關閉,將會導致資料庫系統中的記憶體洩漏,最終將不得不重啟資料庫。還有,這種開發不能控制被建立的連線物件數,系統資源會被毫無顧及的分配出去,如連線過多,也可能導致記憶體洩漏,伺服器崩潰。
資料庫連線池(connection pool)的工作原理
1、基本概念及原理
由上面的分析可以看出,問題的根源就在於對 資料庫連線資源的低效管理。我們知道,
對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配﹑釋放所造成的問題。為解決上述問題,可以採用資料庫連線池技術。資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連線,當需要建立資料庫連線時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。我們可以通過設定連線池最大連線數來防止系統無盡的與資料庫連線。更為重要的是我們可以通過連線池的管理機制監視資料庫的連線的數量﹑使用情況,為系統開發﹑測試及效能調整提供依據。連線池的基本工作原理見下圖2。
圖2 連線池的基本工作原理 2、伺服器自帶的連線池 JDBC的API中沒有提供連線池的方法。一些大型的WEB應用伺服器如BEA的WebLogic和IBM的WebSphere等提供了連線池的機制,但是必須有其第三方的專用類方法支援連線池的用法。 連線池關鍵問題分析 1、併發問題 為了使連線管理服務具有最大的通用性,必須考慮多執行緒環境,即併發問題。這個問題相對比較好解決,因為Java語言自身提供了對併發管理的支援,使用synchronized關鍵字即可確保執行緒是同步的。使用方法為直接在類方法前面加上synchronized關鍵字,如: public synchronized Connection getConnection() 2、多資料庫伺服器和多使用者 對於大型的企業級應用,常常需要同時連線不同的資料庫(如連線Oracle和Sybase)。如何連線不同的資料庫呢?我們採用的策略是:設計一個符合單例模式的連線池管理類,在連線池管理類的唯一例項被建立時讀取一個資原始檔,其中資原始檔中存放著多個數據庫的url地址(<poolName.url>)﹑使用者名稱(<poolName.user>)﹑密碼(<poolName.password>)等資訊。如tx.url=192.168.1.123:5000/tx_it,tx.user=cyl,tx.password=123456。根據資原始檔提供的資訊,建立多個連線池類的例項,每一個例項都是一個特定資料庫的連線池。連線池管理類例項為每個連線池例項取一個名字,通過不同的名字來管理不同的連線池。 對於同一個資料庫有多個使用者使用不同的名稱和密碼訪問的情況,也可以通過資原始檔處理,即在資原始檔中設定多個具有相同url地址,但具有不同使用者名稱和密碼的資料庫連線資訊。 3、事務處理 我們知道,事務具有原子性,此時要求對資料庫的操作符合“ALL-ALL-NOTHING”原則,即對於一組SQL語句要麼全做,要麼全不做。
在Java語言中,Connection類本身提供了對事務的支援,可以通過設定Connection的AutoCommit屬性為false,然後顯式的呼叫commit或rollback方法來實現。但要高效的進行Connection複用,就必須提供相應的事務支援機制。可採用每一個事務獨佔一個連線來實現,這種方法可以大大降低事務管理的複雜性。 4、連線池的分配與釋放 連線池的分配與釋放,對系統的效能有很大的影響。合理的分配與釋放,可以提高連線的複用度,從而降低建立新連線的開銷,同時還可以加快使用者的訪問速度。 對於連線的管理可使用空閒池。即把已經建立但尚未分配出去的連線按建立時間存放到一個空閒池中。每當使用者請求一個連線時,系統首先檢查空閒池內有沒有空閒連線。如果有就把建立時間最長(通過容器的順序存放實現)的那個連線分配給他(實際是先做連線是否有效的判斷,如果可用就分配給使用者,如不可用就把這個連線從空閒池刪掉,重新檢測空閒池是否還有連線);如果沒有則檢查當前所開連線池是否達到連線池所允許的最大連線數(maxConn),如果沒有達到,就新建一個連線,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間內有連線被釋放出來就可以把這個連線分配給等待的使用者,如果等待時間超過預定時間timeout,則返回空值(null)。系統對已經分配出去正在使用的連線只做計數,當使用完後再返還給空閒池。對於空閒連線的狀態,可開闢專門的執行緒定時檢測,這樣會花費一定的系統開銷,但可以保證較快的響應速度。也可採取不開闢專門執行緒,只是在分配前檢測的方法。 5、連線池的配置與維護 連線池中到底應該放置多少連線,才能使系統的效能最佳?系統可採取設定最小連線數(minConn)和最大連線數(maxConn)來控制連線池中的連線。最小連線數是系統啟動時連線池所建立的連線數。如果建立過多,則系統啟動就慢,但建立後系統的響應速度會很快;如果建立過少,則系統啟動的很快,響應起來卻慢。這樣,可以在開發時,設定較小的最小連線數,開發起來會快,而在系統實際使用時設定較大的,因為這樣對訪問客戶來說速度會快些。最大連線數是連線池中允許連線的最大數目,具體設定多少,要看系統的訪問量,可通過反覆測試,找到最佳點。 如何確保連線池中的最小連線數呢?有動態和靜態兩種策略。動態即每隔一定時間就對連線池進行檢測,如果發現連線數量小於最小連線數,則補充相應數量的新連線,以保證連線池的正常運轉。靜態是發現空閒連線不夠時再去檢查。
連線池的實現 1、連線池模型 本文討論的連線池包括一個連線池類(DBConnectionPool)和一個連線池管理類(DBConnetionPoolManager)和一個配置檔案操作類(ParseDSConfig)。連線池類是對某一資料庫所有連線的“緩衝池”,主要實現以下功能:①從連線池獲取或建立可用連線;②使用完畢之後,把連線返還給連線池;③在系統關閉前,斷開所有連線並釋放連線佔用的系統資源;④還能夠處理無效連線(原來登記為可用的連線,由於某種原因不再可用,如超時,通訊問題),並能夠限制連線池中的連線總數不低於某個預定值和不超過某個預定值。(5)當多資料庫時,且資料庫是動態增加的話,將會加到配置檔案中。 連線池管理類是連線池類的外覆類(wrapper),符合單例模式,即系統中只能有一個連線池管理類的例項。其主要用於對多個連線池物件的管理,具有以下功能:①裝載並註冊特定資料庫的JDBC驅動程式;②根據屬性檔案給定的資訊,建立連線池物件;③為方便管理多個連線池物件,為每一個連線池物件取一個名字,實現連線池名字與其例項之間的對映;④跟蹤客戶使用連線情況,以便需要是關閉連線釋放資源。連線池管理類的引入主要是為了方便對多個連線池的使用和管理,如系統需要連線不同的資料庫,或連線相同的資料庫但由於安全性問題,需要不同的使用者使用不同的名稱和密碼。
2、連線池實現(經過本人改版,可以適用多資料庫型別的應用以及一種資料庫型別多個數據庫且資料 庫的數量可以動態增加的應用程式)
1),DBConnectionPool.java 資料庫連線池類
2),DBConnectionManager .java 資料庫管理類
3),DSConfigBean .java 單個數據庫連線資訊Bean
4),ParseDSConfig.java 操作多(這個'多'包括不同的資料庫和同一種資料庫有多個數據庫)
資料 配置檔案xml
5),ds.config.xml 資料庫配置檔案xml
原始碼如下:
DBConnectionPool.java
----------------------------------------------------------
/**
* 資料庫連線池類
*/
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; //使用的連線數
private ArrayList freeConnections = new ArrayList();//容器,空閒連線
private int minConn; //最小連線數
private int maxConn; //最大連線
private String name; //連線池名字
private String password; //密碼
private String url; //資料庫連線地址
private String driver; //驅動
private String user; //使用者名稱
public Timer timer; //定時
/**
*
*/
public DBConnectionPool() {
// TODO Auto-generated constructor stub
}
/**
* 建立連線池
* @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 根據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); //繼續獲得連線
}
else
{
con=newConnection(); //新建連線
}
if(this.maxConn==0||this.maxConn<this.inUsed)
{
con=null;//達到最大連線數,暫時不能獲得連線了。
}
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(); //繼續獲得連線
}
else
{
con=newConnection(); //新建連線
}
if(this.maxConn==0||this.maxConn<this.inUsed)
{
con=null;//等待 超過最大連線時
}
if(con!=null)
{
this.inUsed++;
System.out.println("得到 "+this.name+" 的連線,現有"+inUsed+"個連線在使用!");
}
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();
}
/**
* 建立新連線
* @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;
}
/**
* 定時處理函式
*/
public synchronized void TimerEvent()
{
//暫時還沒有實現以後會加上的
} /**
* @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
------------------------------------------
/**
* 資料庫連線池管理類
*/
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;//唯一資料庫連線池管理例項類
static private int clients; //客戶連線數
private Vector drivers = new Vector();//驅動資訊
private Hashtable pools=new Hashtable();//連線池
/**
* 例項化管理類
*/
public DBConnectionManager() {
// TODO Auto-generated constructor stub
this.init();
}
/**
* 得到唯一例項管理類
* @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);//根據關鍵名字得到連線池
if(pool!=null)
pool.freeConnection(con);//釋放連線
}
/**
* 得到一個連線根據連線池的名字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;
}
/**
* 得到一個連線,根據連線池的名字和等待時間
* @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();
} /**
* 建立連線池
* @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);
}
/**
* 初始化連線池的引數
*/
private void init()
{
//載入驅動程式
this.loadDrivers();
//建立連線池
Iterator alldriver=drivers.iterator();
while(alldriver.hasNext())
{
this.createPools((DSConfigBean)alldriver.next());
System.out.println("建立連線池。。。");
}
System.out.println("建立連線池完畢。。。");
} /**
* 載入驅動程式
* @param props
*/
private void loadDrivers()
{
ParseDSConfig pd=new ParseDSConfig();
//讀取資料庫配置檔案
drivers=pd.readConfigInfo("ds.config.xml");
System.out.println("載入驅動程式。。。");
}
/**
* @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 =""; //資料庫型別
private String name =""; //連線池名字
private String driver =""; //資料庫驅動
private String url =""; //資料庫url
private String username =""; //使用者名稱
private String password =""; //密碼
private int maxconn =0; //最大連線數
/**
*
*/
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 { /**
* 建構函式
*/
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;
}
/**
*修改配置檔案 沒時間寫 過段時間再貼上去 其實一樣的
*/
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"); //建立新連線池
Element pooltype=new Element("type"); //設定連線池型別
pooltype.setText(dsb.getType());
newpool.addContent(pooltype);
Element poolname=new Element("name");//設定連線池名字
poolname.setText(dsb.getName());
newpool.addContent(poolname);
Element pooldriver=new Element("driver"); //設定連線池驅動
pooldriver.addContent(dsb.getDriver());
newpool.addContent(pooldriver);
Element poolurl=new Element("url");//設定連線池url
poolurl.setText(dsb.getUrl());
newpool.addContent(poolurl);
Element poolusername=new Element("username");//設定連線池使用者名稱
poolusername.setText(dsb.getUsername());
newpool.addContent(poolusername);
Element poolpassword=new Element("password");//設定連線池密碼
poolpassword.setText(dsb.getPassword());
newpool.addContent(poolpassword);
Element poolmaxconn=new Element("maxconn");//設定連線池最大連線
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();//得到唯一例項
//得到連線
String name="mysql";//從上下文得到你要訪問的資料庫的名字
Connection con=connectionMan.getConnection(name);
//使用
。。。。。。。
// 使用完畢
connectionMan.freeConnection(name,con);//釋放,但並未斷開連線
2。資料庫連線的動態增加和連線池的動態增加
1。呼叫xml操作增加類
2。重新例項華連線池管理池類
近年來,隨著Internet/Intranet建網技術的飛速發展和在世界範圍內的迅速普及,計算機
應用程式已從傳統的桌面應用轉到Web應用。基於B/S(Browser/Server)架構的3層開發模式逐漸取代C/S(Client/Server)架構的開發模式,成為開發企業級應用和電子商務普遍採用的技術。在Web應用開發的早期,主要使用的技術是CGI﹑ASP﹑PHP等。之後,Sun公司推出了基於Java語言的Servlet+Jsp+JavaBean技術。相比傳統的開發技術,它具有跨平臺﹑安全﹑有效﹑可移植等特性,這使其更便於使用和開發。
Java應用程式訪問資料庫的基本原理
在Java語言中,JDBC(Java DataBase Connection)是應用程式與資料庫溝通的橋樑,
即Java語言通過JDBC技術訪問資料庫。JDBC是一種“開放”的方案,它為資料庫應用開發人員﹑資料庫前臺工具開發人員提供了一種標準的應用程式設計介面,使開發人員可以用純Java語言編寫完整的資料庫應用程式。JDBC提供兩種API,分別是面向開發人員的API和麵向底層的JDBC驅動程式API,底層主要通過直接的JDBC驅動和JDBC-ODBC橋驅動實現與資料庫的連線。
一般來說,Java應用程式訪問資料庫的過程(如圖1所示)是:
①裝載資料庫驅動程式;
②通過JDBC建立資料庫連線;
③訪問資料庫,執行SQL語句;
④斷開資料庫連線。
圖1 Java資料庫訪問機制 JDBC作為一種資料庫訪問技術,具有簡單易用的優點。但使用這種模式進行Web應用 程式開發,存在很多問題:首先,每一次Web請求都要建立一次資料庫連線。建立連線是一個費時的活動,每次都得花費0.05s~1s的時間,而且系統還要分配記憶體資源。這個時間對於一次或幾次資料庫操作,或許感覺不出系統有多大的開銷。可是對於現在的Web應用,尤其是大型電子商務
由上面的分析可以看出,問題的根源就在於對
圖2 連線池的基本工作原理 2、伺服器自帶的連線池 JDBC的API中沒有提供連線池的方法。一些大型的WEB應用伺服器如BEA的WebLogic和IBM的WebSphere等提供了連線池的機制,但是必須有其第三方的專用類方法支援連線池的用法。 連線池關鍵問題分析 1、併發問題 為了使連線管理服務具有最大的通用性,必須考慮多執行緒環境,即併發問題。這個問題相對比較好解決,因為Java語言自身提供了對併發管理的支援,使用synchronized關鍵字即可確保執行緒是同步的。使用方法為直接在類方法前面加上synchronized關鍵字,如: public synchronized Connection getConnection() 2、多資料庫伺服器和多使用者 對於大型的企業級應用,常常需要同時連線不同的資料庫(如連線Oracle和Sybase)。如何連線不同的資料庫呢?我們採用的策略是:設計一個符合單例模式的連線池管理類,在連線池管理類的唯一例項被建立時讀取一個資原始檔,其中資原始檔中存放著多個數據庫的url地址(<poolName.url>)﹑使用者名稱(<poolName.user>)﹑密碼(<poolName.password>)等資訊。如tx.url=192.168.1.123:5000/tx_it,tx.user=cyl,tx.password=123456。根據資原始檔提供的資訊,建立多個連線池類的例項,每一個例項都是一個特定資料庫的連線池。連線池管理類例項為每個連線池例項取一個名字,通過不同的名字來管理不同的連線池。 對於同一個資料庫有多個使用者使用不同的名稱和密碼訪問的情況,也可以通過資原始檔處理,即在資原始檔中設定多個具有相同url地址,但具有不同使用者名稱和密碼的資料庫連線資訊。 3、事務處理 我們知道,事務具有原子性,此時要求對資料庫的操作符合“ALL-ALL-NOTHING”原則,即對於一組SQL語句要麼全做,要麼全不做。
在Java語言中,Connection類本身提供了對事務的支援,可以通過設定Connection的AutoCommit屬性為false,然後顯式的呼叫commit或rollback方法來實現。但要高效的進行Connection複用,就必須提供相應的事務支援機制。可採用每一個事務獨佔一個連線來實現,這種方法可以大大降低事務管理的複雜性。 4、連線池的分配與釋放 連線池的分配與釋放,對系統的效能有很大的影響。合理的分配與釋放,可以提高連線的複用度,從而降低建立新連線的開銷,同時還可以加快使用者的訪問速度。 對於連線的管理可使用空閒池。即把已經建立但尚未分配出去的連線按建立時間存放到一個空閒池中。每當使用者請求一個連線時,系統首先檢查空閒池內有沒有空閒連線。如果有就把建立時間最長(通過容器的順序存放實現)的那個連線分配給他(實際是先做連線是否有效的判斷,如果可用就分配給使用者,如不可用就把這個連線從空閒池刪掉,重新檢測空閒池是否還有連線);如果沒有則檢查當前所開連線池是否達到連線池所允許的最大連線數(maxConn),如果沒有達到,就新建一個連線,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間內有連線被釋放出來就可以把這個連線分配給等待的使用者,如果等待時間超過預定時間timeout,則返回空值(null)。系統對已經分配出去正在使用的連線只做計數,當使用完後再返還給空閒池。對於空閒連線的狀態,可開闢專門的執行緒定時檢測,這樣會花費一定的系統開銷,但可以保證較快的響應速度。也可採取不開闢專門執行緒,只是在分配前檢測的方法。 5、連線池的配置與維護 連線池中到底應該放置多少連線,才能使系統的效能最佳?系統可採取設定最小連線數(minConn)和最大連線數(maxConn)來控制連線池中的連線。最小連線數是系統啟動時連線池所建立的連線數。如果建立過多,則系統啟動就慢,但建立後系統的響應速度會很快;如果建立過少,則系統啟動的很快,響應起來卻慢。這樣,可以在開發時,設定較小的最小連線數,開發起來會快,而在系統實際使用時設定較大的,因為這樣對訪問客戶來說速度會快些。最大連線數是連線池中允許連線的最大數目,具體設定多少,要看系統的訪問量,可通過反覆測試,找到最佳點。 如何確保連線池中的最小連線數呢?有動態和靜態兩種策略。動態即每隔一定時間就對連線池進行檢測,如果發現連線數量小於最小連線數,則補充相應數量的新連線,以保證連線池的正常運轉。靜態是發現空閒連線不夠時再去檢查。
連線池的實現 1、連線池模型 本文討論的連線池包括一個連線池類(DBConnectionPool)和一個連線池管理類(DBConnetionPoolManager)和一個配置檔案操作類(ParseDSConfig)。連線池類是對某一資料庫所有連線的“緩衝池”,主要實現以下功能:①從連線池獲取或建立可用連線;②使用完畢之後,把連線返還給連線池;③在系統關閉前,斷開所有連線並釋放連線佔用的系統資源;④還能夠處理無效連線(原來登記為可用的連線,由於某種原因不再可用,如超時,通訊問題),並能夠限制連線池中的連線總數不低於某個預定值和不超過某個預定值。(5)當多資料庫時,且資料庫是動態增加的話,將會加到配置檔案中。 連線池管理類是連線池類的外覆類(wrapper),符合單例模式,即系統中只能有一個連線池管理類的例項。其主要用於對多個連線池物件的管理,具有以下功能:①裝載並註冊特定資料庫的JDBC驅動程式;②根據屬性檔案給定的資訊,建立連線池物件;③為方便管理多個連線池物件,為每一個連線池物件取一個名字,實現連線池名字與其例項之間的對映;④跟蹤客戶使用連線情況,以便需要是關閉連線釋放資源。連線池管理類的引入主要是為了方便對多個連線池的使用和管理,如系統需要連線不同的資料庫,或連線相同的資料庫但由於安全性問題,需要不同的使用者使用不同的名稱和密碼。
2、連線池實現(經過本人改版,可以適用多資料庫型別的應用以及一種資料庫型別多個數據庫且資料 庫的數量可以動態增加的應用程式)
1),DBConnectionPool.java 資料庫連線池類
2),DBConnectionManager .java 資料庫管理類
3),DSConfigBean .java 單個數據庫連線資訊Bean
4),ParseDSConfig.java 操作多(這個'多'包括不同的資料庫和同一種資料庫有多個數據庫)
資料 配置檔案xml
5),ds.config.xml 資料庫配置檔案xml
原始碼如下:
DBConnectionPool.java
----------------------------------------------------------
/**
* 資料庫連線池類
*/
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; //使用的連線數
private ArrayList freeConnections = new ArrayList();//容器,空閒連線
private int minConn; //最小連線數
private int maxConn; //最大連線
private String name; //連線池名字
private String password; //密碼
private String url; //資料庫連線地址
private String driver; //驅動
private String user; //使用者名稱
public Timer timer; //定時
/**
*
*/
public DBConnectionPool() {
// TODO Auto-generated constructor stub
}
/**
* 建立連線池
* @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 根據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); //繼續獲得連線
}
else
{
con=newConnection(); //新建連線
}
if(this.maxConn==0||this.maxConn<this.inUsed)
{
con=null;//達到最大連線數,暫時不能獲得連線了。
}
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(); //繼續獲得連線
}
else
{
con=newConnection(); //新建連線
}
if(this.maxConn==0||this.maxConn<this.inUsed)
{
con=null;//等待 超過最大連線時
}
if(con!=null)
{
this.inUsed++;
System.out.println("得到 "+this.name+" 的連線,現有"+inUsed+"個連線在使用!");
}
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();
}
/**
* 建立新連線
* @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;
}
/**
* 定時處理函式
*/
public synchronized void TimerEvent()
{
//暫時還沒有實現以後會加上的
} /**
* @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
------------------------------------------
/**
* 資料庫連線池管理類
*/
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;//唯一資料庫連線池管理例項類
static private int clients; //客戶連線數
private Vector drivers = new Vector();//驅動資訊
private Hashtable pools=new Hashtable();//連線池
/**
* 例項化管理類
*/
public DBConnectionManager() {
// TODO Auto-generated constructor stub
this.init();
}
/**
* 得到唯一例項管理類
* @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);//根據關鍵名字得到連線池
if(pool!=null)
pool.freeConnection(con);//釋放連線
}
/**
* 得到一個連線根據連線池的名字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;
}
/**
* 得到一個連線,根據連線池的名字和等待時間
* @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();
} /**
* 建立連線池
* @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);
}
/**
* 初始化連線池的引數
*/
private void init()
{
//載入驅動程式
this.loadDrivers();
//建立連線池
Iterator alldriver=drivers.iterator();
while(alldriver.hasNext())
{
this.createPools((DSConfigBean)alldriver.next());
System.out.println("建立連線池。。。");
}
System.out.println("建立連線池完畢。。。");
} /**
* 載入驅動程式
* @param props
*/
private void loadDrivers()
{
ParseDSConfig pd=new ParseDSConfig();
//讀取資料庫配置檔案
drivers=pd.readConfigInfo("ds.config.xml");
System.out.println("載入驅動程式。。。");
}
/**
* @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 =""; //資料庫型別
private String name =""; //連線池名字
private String driver =""; //資料庫驅動
private String url =""; //資料庫url
private String username =""; //使用者名稱
private String password =""; //密碼
private int maxconn =0; //最大連線數
/**
*
*/
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 { /**
* 建構函式
*/
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;
}
/**
*修改配置檔案 沒時間寫 過段時間再貼上去 其實一樣的
*/
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"); //建立新連線池
Element pooltype=new Element("type"); //設定連線池型別
pooltype.setText(dsb.getType());
newpool.addContent(pooltype);
Element poolname=new Element("name");//設定連線池名字
poolname.setText(dsb.getName());
newpool.addContent(poolname);
Element pooldriver=new Element("driver"); //設定連線池驅動
pooldriver.addContent(dsb.getDriver());
newpool.addContent(pooldriver);
Element poolurl=new Element("url");//設定連線池url
poolurl.setText(dsb.getUrl());
newpool.addContent(poolurl);
Element poolusername=new Element("username");//設定連線池使用者名稱
poolusername.setText(dsb.getUsername());
newpool.addContent(poolusername);
Element poolpassword=new Element("password");//設定連線池密碼
poolpassword.setText(dsb.getPassword());
newpool.addContent(poolpassword);
Element poolmaxconn=new Element("maxconn");//設定連線池最大連線
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();//得到唯一例項
//得到連線
String name="mysql";//從上下文得到你要訪問的資料庫的名字
Connection con=connectionMan.getConnection(name);
//使用
。。。。。。。
// 使用完畢
connectionMan.freeConnection(name,con);//釋放,但並未斷開連線
2。資料庫連線的動態增加和連線池的動態增加
1。呼叫xml操作增加類
2。重新例項華連線池管理池類