作者--
joinme這是一篇基礎(chǔ)性文章,主要介紹了jdbc在流行數(shù)據(jù)庫(sql server,oracle)方面的應(yīng)用。但是都是個人觀點,所以不能保證完全正確,僅供參考,如果有不同意見可以在評論中指出,我會做相應(yīng)的修改。:)
一般情況下,直接用jdbc等東西連數(shù)據(jù)庫時,比較常用連數(shù)據(jù)庫的代碼可能是:
?? private Connection conn
?? private String poolURL = "";
?? private String driverName ="";
?? private String user=""
?? private String pass="";
?? private DBConnProxy Proxy; //自己寫的class,起控制數(shù)據(jù)庫訪問作用
public Object getConn()
????{
??????try
?????????? {
?????????????????????? Properties??prop=new Properties();
?????????????????????? prop.setProperty("user",user);
?????????????????????? prop.setProperty("password",pass);
?????????????????????? Driver mydriver=(Driver)Class.forName(driverName).newInstance();
?????????????????????? conn = mydriver.connect(poolURL,prop);//或者conn = mydriver.connect(poolURL,null);具體什么時候用我還的請教高手。
??????????????????/*
???????????????? 或者:
????????????????Class.forName(driverName);
????????????????conn=DriverManager.getConnection(poolURL, user, pass);
????????????????*/
?????????? }
??????catch ( Exception??e )
??{
?? System.out.println("打開數(shù)據(jù)庫出錯\n" + e.getMessage());
??}
????????????????if(!Proxy.getDB() ){
??????????????????this.Close()
??????????????????return null;
????????????????}
?? return conn;
??????}
其中的 driverName,poolURL,user,pass都可以通過讀取 xml文件或普通屬性文件獲取。而是連sqlserver還是oracle就只是改改配置就可以了。
它們都可以用 sun.jdbc.odbc.JdbcOdbcDriver 來連。對應(yīng)poolURL="jdbc:odbc:test",user,pass略
也可以用自己特有的:
sqlserver:weblogic.jdbc.mssqlserver4.Driver (網(wǎng)上下) 對應(yīng)poolURL="jdbc:weblogic:mssqlserver4:ceic@127.0.0.1" //ceic是數(shù)據(jù)庫名,127.0.0.1是數(shù)據(jù)源位置,可以是遠程的數(shù)據(jù)庫,user,pass略
oracle:oracle.jdbc.driver.OracleDriver (class12.zip,裝了oracle就應(yīng)該有了) 對應(yīng)jdbc:oracle:thin:scott/tiger@10.1.103.234:1521:sp"??scott/tiger連接身份的用戶名/密碼,10.1.103.234,數(shù)據(jù)源ip,1521:端口(默認是1521). sp指向數(shù)據(jù)庫名user,pass略
如果用的weblogic配的數(shù)據(jù)庫連接,可以通過
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("forceicdatasource"); //forceicdatasource是配的datasource.也可以通過和上面統(tǒng)一的方法來調(diào)用。
weblogic:weblogic.jdbc.pool.Driver //driverName
對應(yīng)的poolURL="jdbc:weblogic:pool:poolname" //poolname是在weblogic中配的jdbc類型的connections pool的名字。user,pass是weblogic用戶(administrators用戶組中的用戶)的用戶名和密碼。(如果不是用DriverManager就用不上,"conn = mydriver.connect(poolURL,null);"就是在這種情況下可以用。我在weblogic 6.1下測試通過)
綜上說的,可以看出,大多數(shù)數(shù)據(jù)庫連接都可以通過配置 屬性文件 來靈活的獲取。(移植起來很是方便,并且對應(yīng)用基本沒有什么影響,當然也可以夸平臺)所以我可以通過動態(tài)讀取屬性文件來解決。
private String javaHome = System.getProperty("java.home");
private final String FS = System.getProperty("file.separator");
private String path = javaHome+FS+"db.properties"; //把db.properties放在系統(tǒng)屬性java.home下,一般是jdk目錄下的 jre目錄里。
public boolean getInfo(){
File file=new java.io.File(path);
Properties pro=new Properties();
boolean readsucced;
try{
InputStream in=new BufferedInputStream(new FileInputStream(file));
pro.load(in);
driverName=pro.getProperty("driverName");
poolURL=pro.getProperty("poolURL") ;
user=pro.getProperty("user") ;
pass=pro.getProperty("pass") ;
//自己把它們trim()掉。我就偷懶不寫了。
readsucced=true;
}catch(Exception e){System.out.println("讀取屬性文件出錯");readsucced=false;}
return readsucced;
}
不過一般只用讀一次就可以了。所以可以把它放在 static{}塊里,也可以放在構(gòu)造器里面(然后和放在靜態(tài)連接池,如果是單獨的應(yīng)用,應(yīng)該把getInfo()作為靜態(tài)類和數(shù)據(jù)庫連接類分開)。
public DBConn() {
setDBConnProxy(ProxyFactory.DefaultType );//設(shè)定連接proxy,控制數(shù)據(jù)庫連接頻率,可能會犧牲效力,不過在防止惡意破壞上有點作用,自己寫的畢竟趕不上weblogic的連接池了。所以只好做點小的防范措施.如果是用weblogic配的連接池,可以直接在proxyFactory里面加個什么都不做的proxy.
getInfo();
}
屬性文件db.properties內(nèi)容如下:
driverName=sun.jdbc.odbc.JdbcOdbcDriver
poolURL=jdbc:odbc:test
user=sa
pass=1234Q_Q5678
自己可以耕具實際情況去更改屬性文件。
注: getConn()方法返回的是 Object,是不同的數(shù)據(jù)庫連接有不同的擴展應(yīng)用,比如oracle的就有針對clob,blob的應(yīng)用(用class12.zip的情況下),普通的connection不能滿足,所以可以通過在應(yīng)用中把getConn()返回的Object轉(zhuǎn)化成OracleConnection來用。(個人觀點,不知道有沒有更好的解決方法)
上面寫的這么多,可能只對新手有點用處,在j2ee風(fēng)行的今天已經(jīng)很落伍了,還希望高手指出問題一起討論(還沒有有關(guān)于mysql的連接辦法,沒有做過,希望有人能補充上來)。
————————————————————————————————————————
使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池
數(shù)據(jù)庫連接池在編寫應(yīng)用服務(wù)是經(jīng)常需要用到的模塊,太過頻繁的連接數(shù)據(jù)庫對服務(wù)性能來講是一個瓶頸,使用緩沖池技術(shù)可以來消除這個瓶頸。我們可以在互聯(lián)網(wǎng)上找到很多關(guān)于數(shù)據(jù)庫連接池的源程序,但是都發(fā)現(xiàn)這樣一個共同的問題:這些連接池的實現(xiàn)方法都不同程度地增加了與使用者之間的耦合度。很多的連接池都要求用戶通過其規(guī)定的方法獲取數(shù)據(jù)庫的連接,這一點我們可以理解,畢竟目前所有的應(yīng)用服務(wù)器取數(shù)據(jù)庫連接的方式都是這種方式實現(xiàn)的。但是另外一個共同的問題是,它們同時不允許使用者顯式的調(diào)用Connection.close()方法,而需要用其規(guī)定的一個方法來關(guān)閉連接。這種做法有兩個缺點:
第一:改變了用戶使用習(xí)慣,增加了用戶的使用難度。
首先我們來看看一個正常的數(shù)據(jù)庫操作過程:
int executeSQL(String sql) throws SQLException
{
????????Connection conn = getConnection();????????//通過某種方式獲取數(shù)據(jù)庫連接
????????PreparedStatement ps = null;
????????int res = 0;
????????try{
????????????????ps = conn.prepareStatement(sql);
????????????????res = ps.executeUpdate();
}finally{
try{
ps.close();
}catch(Exception e){}
try{
????????conn.close();//
}catch(Exception e){}
}
return res;
}
使用者在用完數(shù)據(jù)庫連接后通常是直接調(diào)用連接的方法close來釋放數(shù)據(jù)庫資源,如果用我們前面提到的連接池的實現(xiàn)方法,那語句conn.close()將被某些特定的語句所替代。
第二:使連接池?zé)o法對之中的所有連接進行獨占控制。由于連接池不允許用戶直接調(diào)用連接的close方法,一旦使用者在使用的過程中由于習(xí)慣問題直接關(guān)閉了數(shù)據(jù)庫連接,那么連接池將無法正常維護所有連接的狀態(tài),考慮連接池和應(yīng)用由不同開發(fā)人員實現(xiàn)時這種問題更容易出現(xiàn)。
綜合上面提到的兩個問題,我們來討論一下如何解決這兩個要命的問題。
首先我們先設(shè)身處地的考慮一下用戶是想怎么樣來使用這個數(shù)據(jù)庫連接池的。用戶可以通過特定的方法來獲取數(shù)據(jù)庫的連接,同時這個連接的類型應(yīng)該是標準的java.sql.Connection。用戶在獲取到這個數(shù)據(jù)庫連接后可以對這個連接進行任意的操作,包括關(guān)閉連接等。
通過對用戶使用的描述,怎樣可以接管Connection.close方法就成了我們這篇文章的主題。
為了接管數(shù)據(jù)庫連接的close方法,我們應(yīng)該有一種類似于鉤子的機制。例如在Windows編程中我們可以利用Hook API來實現(xiàn)對某個Windows API的接管。在JAVA中同樣也有這樣一個機制。JAVA提供了一個Proxy類和一個InvocationHandler,這兩個類都在java.lang.reflect包中。我們先來看看SUN公司提供的文檔是怎么描述這兩個類的。
public interface InvocationHandler
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
Each proxy instance has an associated invocation handler.
When a method is invoked on a proxy instance,
the method invocation is encoded and dispatched to the invoke method of its invocation handler.
SUN的API文檔中關(guān)于Proxy的描述很多,這里就不羅列出來。通過文檔對接口InvocationHandler的描述我們可以看到當調(diào)用一個Proxy實例的方法時會觸發(fā)Invocationhanlder的invoke方法。從JAVA的文檔中我們也同時了解到這種動態(tài)代理機制只能接管接口的方法,而對一般的類無效,考慮到j(luò)ava.sql.Connection本身也是一個接口由此就找到了解決如何接管close方法的出路。
首先,我們先定義一個數(shù)據(jù)庫連接池參數(shù)的類,定義了數(shù)據(jù)庫的JDBC驅(qū)動程序類名,連接的URL以及用戶名口令等等一些信息,該類是用于初始化連接池的參數(shù),具體定義如下:
public class ConnectionParam implements Serializable
{
????????private String driver;????????????????????????????????//數(shù)據(jù)庫驅(qū)動程序
????????private String url;????????????????????????????????????????//數(shù)據(jù)連接的URL
????????private String user;????????????????????????????????????????//數(shù)據(jù)庫用戶名
????????private String password;????????????????????????????????//數(shù)據(jù)庫密碼
????????private int minConnection = 0;????????????????//初始化連接數(shù)
????????private int maxConnection = 50;????????????????//最大連接數(shù)
????????private long timeoutValue = 600000;//連接的最大空閑時間
????????private long waitTime = 30000;????????????????//取連接的時候如果沒有可用連接最大的等待時間
其次是連接池的工廠類ConnectionFactory,通過該類來將一個連接池對象與一個名稱對應(yīng)起來,使用者通過該名稱就可以獲取指定的連接池對象,具體代碼如下:
/**
* 連接池類廠,該類常用來保存多個數(shù)據(jù)源名稱合數(shù)據(jù)庫連接池對應(yīng)的哈希
* @author liusoft
*/
public class ConnectionFactory
{
????????//該哈希表用來保存數(shù)據(jù)源名和連接池對象的關(guān)系表
????????static Hashtable connectionPools = null;
????????static{
????????????????connectionPools = new Hashtable(2,0.75F);
????????}
????????/**
???????? * 從連接池工廠中獲取指定名稱對應(yīng)的連接池對象
???????? * @param dataSource????????連接池對象對應(yīng)的名稱
???????? * @return DataSource????????返回名稱對應(yīng)的連接池對象
???????? * @throws NameNotFoundException????????無法找到指定的連接池
???????? */
????????public static DataSource lookup(String dataSource)
????????????????throws NameNotFoundException
????????{
????????????????Object ds = null;
????????????????ds = connectionPools.get(dataSource);
????????????????if(ds == null || !(ds instanceof DataSource))
????????????????????????throw new NameNotFoundException(dataSource);
????????????????return (DataSource)ds;
????????}
????????/**
???????? * 將指定的名字和數(shù)據(jù)庫連接配置綁定在一起并初始化數(shù)據(jù)庫連接池
???????? * @param name????????????????對應(yīng)連接池的名稱
???????? * @param param????????連接池的配置參數(shù),具體請見類ConnectionParam
???????? * @return DataSource????????如果綁定成功后返回連接池對象
???????? * @throws NameAlreadyBoundException????????一定名字name已經(jīng)綁定則拋出該異常
???????? * @throws ClassNotFoundException????????????????無法找到連接池的配置中的驅(qū)動程序類
???????? * @throws IllegalAccessException????????????????連接池配置中的驅(qū)動程序類有誤
???????? * @throws InstantiationException????????????????無法實例化驅(qū)動程序類
???????? * @throws SQLException????????????????????????????????無法正常連接指定的數(shù)據(jù)庫
???????? */
????????public static DataSource bind(String name, ConnectionParam param)
????????????????throws NameAlreadyBoundException,ClassNotFoundException,
????????????????????????????????IllegalAccessException,InstantiationException,SQLException
????????{
????????????????DataSourceImpl source = null;
????????????????try{
????????????????????????lookup(name);
????????????????????????throw new NameAlreadyBoundException(name);
????????????????}catch(NameNotFoundException e){
????????????????????????source = new DataSourceImpl(param);
????????????????????????source.initConnection();
????????????????????????connectionPools.put(name, source);
????????????????}
????????????????return source;
????????}
????????/**
???????? * 重新綁定數(shù)據(jù)庫連接池
???????? * @param name????????????????對應(yīng)連接池的名稱
???????? * @param param????????連接池的配置參數(shù),具體請見類ConnectionParam
???????? * @return DataSource????????如果綁定成功后返回連接池對象
???????? * @throws NameAlreadyBoundException????????一定名字name已經(jīng)綁定則拋出該異常
???????? * @throws ClassNotFoundException????????????????無法找到連接池的配置中的驅(qū)動程序類
???????? * @throws IllegalAccessException????????????????連接池配置中的驅(qū)動程序類有誤
???????? * @throws InstantiationException????????????????無法實例化驅(qū)動程序類
???????? * @throws SQLException????????????????????????????????無法正常連接指定的數(shù)據(jù)庫
???????? */
????????public static DataSource rebind(String name, ConnectionParam param)
????????????????throws NameAlreadyBoundException,ClassNotFoundException,
????????????????????????????????IllegalAccessException,InstantiationException,SQLException
????????{
????????????????try{
????????????????????????unbind(name);
????????????????}catch(Exception e){}
????????????????return bind(name, param);
????????}
????????/**
???????? * 刪除一個數(shù)據(jù)庫連接池對象
???????? * @param name
???????? * @throws NameNotFoundException
???????? */
????????public static void unbind(String name) throws NameNotFoundException
????????{
????????????????DataSource dataSource = lookup(name);
????????????????if(dataSource instanceof DataSourceImpl){
????????????????????????DataSourceImpl dsi = (DataSourceImpl)dataSource;
????????????????????????try{
????????????????????????????????dsi.stop();
????????????????????????????????dsi.close();
????????????????????????}catch(Exception e){
????????????????????????}finally{
????????????????????????????????dsi = null;
????????????????????????}
????????????????}
????????????????connectionPools.remove(name);
????????}
????????
}
ConnectionFactory主要提供了用戶將將連接池綁定到一個具體的名稱上以及取消綁定的操作。使用者只需要關(guān)心這兩個類即可使用數(shù)據(jù)庫連接池的功能。下面我們給出一段如何使用連接池的代碼:
????????String name = "pool";
????????String driver = " sun.jdbc.odbc.JdbcOdbcDriver ";
????????String url = "jdbc:odbc:datasource";
????????ConnectionParam param = new ConnectionParam(driver,url,null,null);
????????param.setMinConnection(1);
????????param.setMaxConnection(5);
????????param.setTimeoutValue(20000);
????????ConnectionFactory.bind(name, param);
????????System.out.println("bind datasource ok.");
????????//以上代碼是用來登記一個連接池對象,該操作可以在程序初始化只做一次即可
????????//以下開始就是使用者真正需要寫的代碼
????????DataSource ds = ConnectionFactory.lookup(name);
????????try{
????????????????for(int i=0;i<10;i++){
????????????????????????Connection conn = ds.getConnection();
????????????????????????try{
????????????????????????????????testSQL(conn, sql);
????????????????????????}finally{
????????????????????????????????try{
????????????????????????????????????????conn.close();
????????????????????????????????}catch(Exception e){}
????????????????????????}
????????????????}
????????}catch(Exception e){
????????????????e.printStackTrace();
????????}finally{
????????????????ConnectionFactory.unbind(name);
????????????????System.out.println("unbind datasource ok.");
????????????????System.exit(0);
????????}
從使用者的示例代碼就可以看出,我們已經(jīng)解決了常規(guī)連接池產(chǎn)生的兩個問題。但是我們最最關(guān)心的是如何解決接管close方法的辦法。接管工作主要在ConnectionFactory中的兩句代碼:
source = new DataSourceImpl(param);
source.initConnection();
DataSourceImpl是一個實現(xiàn)了接口javax.sql.DataSource的類,該類維護著一個連接池的對象。由于該類是一個受保護的類,因此它暴露給使用者的方法只有接口DataSource中定義的方法,其他的所有方法對使用者來說都是不可視的。我們先來關(guān)心用戶可訪問的一個方法getConnection
/**
* @see javax.sql.DataSource#getConnection(String,String)
*/
????????public Connection getConnection(String user, String password) throws SQLException
????????{
????????????????//首先從連接池中找出空閑的對象
????????????????Connection conn = getFreeConnection(0);
????????????????if(conn == null){
????????????????????????//判斷是否超過最大連接數(shù),如果超過最大連接數(shù)
????????????????????????//則等待一定時間查看是否有空閑連接,否則拋出異常告訴用戶無可用連接
????????????????????????if(getConnectionCount() >= connParam.getMaxConnection())
????????????????????????????????conn = getFreeConnection(connParam.getWaitTime());
????????????????????????else{//沒有超過連接數(shù),重新獲取一個數(shù)據(jù)庫的連接
????????????????????????????????connParam.setUser(user);
????????????????????????????????connParam.setPassword(password);
????????????????????????????????Connection conn2 = DriverManager.getConnection(connParam.getUrl(),
????????????????????????????????user, password);
????????????????????????????????//代理將要返回的連接對象
????????????????????????????????_Connection _conn = new _Connection(conn2,true);
????????????????????????????????synchronized(conns){
????????????????????????????????????????conns.add(_conn);
????????????????????????????????}
????????????????????????????????conn = _conn.getConnection();
????????????????????????}
????????????????}
????????????????return conn;
????????}
????????/**
???????? * 從連接池中取一個空閑的連接
???????? * @param nTimeout????????如果該參數(shù)值為0則沒有連接時只是返回一個null
???????? * 否則的話等待nTimeout毫秒看是否還有空閑連接,如果沒有拋出異常
???????? * @return Connection
???????? * @throws SQLException
???????? */
????????protected synchronized Connection getFreeConnection(long nTimeout)
????????????????throws SQLException
????????{
????????????????Connection conn = null;
????????????????Iterator iter = conns.iterator();
????????????????while(iter.hasNext()){
????????????????????????_Connection _conn = (_Connection)iter.next();
????????????????????????if(!_conn.isInUse()){
????????????????????????????????conn = _conn.getConnection();
????????????????????????????????_conn.setInUse(true);????????????????????????????????
????????????????????????????????break;
????????????????????????}
????????????????}
????????????????if(conn == null && nTimeout > 0){
????????????????????????//等待nTimeout毫秒以便看是否有空閑連接
????????????????????????try{
????????????????????????????????Thread.sleep(nTimeout);
????????????????????????}catch(Exception e){}
????????????????????????conn = getFreeConnection(0);
????????????????????????if(conn == null)
????????????????????????????????throw new SQLException("沒有可用的數(shù)據(jù)庫連接");
????????????????}
????????????????return conn;
????????}
DataSourceImpl類中實現(xiàn)getConnection方法的跟正常的數(shù)據(jù)庫連接池的邏輯是一致的,首先判斷是否有空閑的連接,如果沒有的話判斷連接數(shù)是否已經(jīng)超過最大連接數(shù)等等的一些邏輯。但是有一點不同的是通過DriverManager得到的數(shù)據(jù)庫連接并不是及時返回的,而是通過一個叫_Connection的類中介一下,然后調(diào)用_Connection.getConnection返回的。如果我們沒有通過一個中介也就是JAVA中的Proxy來接管要返回的接口對象,那么我們就沒有辦法截住Connection.close方法。
終于到了核心所在,我們先來看看_Connection是如何實現(xiàn)的,然后再介紹是客戶端調(diào)用Connection.close方法時走的是怎樣一個流程,為什么并沒有真正的關(guān)閉連接。
/**
* 數(shù)據(jù)連接的自封裝,屏蔽了close方法
* @author Liudong
*/
class _Connection implements InvocationHandler
{
????????private final static String CLOSE_METHOD_NAME = "close";
????????private Connection conn = null;
????????//數(shù)據(jù)庫的忙狀態(tài)
????????private boolean inUse = false;
????????//用戶最后一次訪問該連接方法的時間
????????private long lastAccessTime = System.currentTimeMillis();
????????
????????_Connection(Connection conn, boolean inUse){
????????????????this.conn = conn;
????????????????this.inUse = inUse;
????????}
????????/**
???????? * Returns the conn.
???????? * @return Connection
???????? */
????????public Connection getConnection() {
????????????????//返回數(shù)據(jù)庫連接conn的接管類,以便截住close方法
????????????????Connection conn2 = (Connection)Proxy.newProxyInstance(
????????????????????????conn.getClass().getClassLoader(),
????????????????????????conn.getClass().getInterfaces(),this);
????????????????return conn2;
????????}
????????/**
???????? * 該方法真正的關(guān)閉了數(shù)據(jù)庫的連接
???????? * @throws SQLException
???????? */
????????void close() throws SQLException{
????????????????//由于類屬性conn是沒有被接管的連接,因此一旦調(diào)用close方法后就直接關(guān)閉連接
????????????????conn.close();
????????}
????????/**
???????? * Returns the inUse.
???????? * @return boolean
???????? */
????????public boolean isInUse() {
????????????????return inUse;
????????}
????????/**
???????? * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object)
???????? */
????????public Object invoke(Object proxy, Method m, Object[] args)
????????????????throws Throwable
????????{
????????????????Object obj = null;
????????????????//判斷是否調(diào)用了close的方法,如果調(diào)用close方法則把連接置為無用狀態(tài)
????????????????if(CLOSE_METHOD_NAME.equals(m.getName()))
????????????????????????setInUse(false);????????????????
????????????????else
????????????????????????obj = m.invoke(conn, args);????????
????????????????//設(shè)置最后一次訪問時間,以便及時清除超時的連接
????????????????lastAccessTime = System.currentTimeMillis();
????????????????return obj;
????????}
????????????????
????????/**
???????? * Returns the lastAccessTime.
???????? * @return long
???????? */
????????public long getLastAccessTime() {
????????????????return lastAccessTime;
????????}
????????/**
???????? * Sets the inUse.
???????? * @param inUse The inUse to set
???????? */
????????public void setInUse(boolean inUse) {
????????????????this.inUse = inUse;
????????}
}
一旦使用者調(diào)用所得到連接的close方法,由于用戶的連接對象是經(jīng)過接管后的對象,因此JAVA虛擬機會首先調(diào)用_Connection.invoke方法,在該方法中首先判斷是否為close方法,如果不是則將代碼轉(zhuǎn)給真正的沒有被接管的連接對象conn。否則的話只是簡單的將該連接的狀態(tài)設(shè)置為可用。到此您可能就明白了整個接管的過程,但是同時也有一個疑問:這樣的話是不是這些已建立的連接就始終沒有辦法真正關(guān)閉?答案是可以的。我們來看看ConnectionFactory.unbind方法,該方法首先找到名字對應(yīng)的連接池對象,然后關(guān)閉該連接池中的所有連接并刪除掉連接池。在DataSourceImpl類中定義了一個close方法用來關(guān)閉所有的連接,詳細代碼如下:
????????/**
???????? * 關(guān)閉該連接池中的所有數(shù)據(jù)庫連接
???????? * @return int 返回被關(guān)閉連接的個數(shù)
???????? * @throws SQLException
???????? */
????????public int close() throws SQLException
????????{
????????????????int cc = 0;
????????????????SQLException excp = null;
????????????????Iterator iter = conns.iterator();
????????????????while(iter.hasNext()){
????????????????????????try{
????????????????????????????????((_Connection)iter.next()).close();
????????????????????????????????cc ++;
????????????????????????}catch(Exception e){
????????????????????????????????if(e instanceof SQLException)
????????????????????????????????????????excp = (SQLException)e;
????????????????????????}
????????????????}
????????????????if(excp != null)
????????????????????????throw excp;
????????????????return cc;
????????}
該方法一一調(diào)用連接池中每個對象的close方法,這個close方法對應(yīng)的是_Connection中對close的實現(xiàn),在_Connection定義中關(guān)閉數(shù)據(jù)庫連接的時候是直接調(diào)用沒有經(jīng)過接管的對象的關(guān)閉方法,因此該close方法真正的釋放了數(shù)據(jù)庫資源。
以上文字只是描述了接口方法的接管,具體一個實用的連接池模塊還需要對空閑連接的監(jiān)控并及時釋放連接,詳細的代碼請參照附件。
參考資料:
http://java.sun.com
JAVA的官方網(wǎng)站
from-ibm developer
——————————————————————————————————————————
??1
package?dbo;
??2
import?java.sql.*;
??3
import?java.util.*;
??4
??5
public?class?DBO
??6

{
??7
????Connection?conn;
??8
????String?user="[username]";?????????????????//[password]為您連接數(shù)據(jù)庫的用戶名
??9
????String?password="[password]";?????????????//[password]為您連接數(shù)據(jù)庫的密碼
?10
?11
????public?DBO()
?12
????
{
?13
????try?
{
?14
????????????Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
?15
????????}?catch?(ClassNotFoundException?e)
?16
????????
{
?17
????????????e.printStackTrace();
?18
????????}
?19
????String?url="jdbc:odbc:BBS";
?20
????try?
{
?21
?????????conn=?DriverManager.getConnection(url);
?22
????????}?catch?(SQLException?e)
?23
????????
{
?24
????????????e.printStackTrace();
?25
????????}
?26
????}
?27
?28
/**//*
?29
///////////////////////////////Access數(shù)據(jù)庫(ODBC數(shù)據(jù)源)
?30
?31
????public?DBO()
?32
????{
?33
????try?{
?34
????????????Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
?35
????????}
?36
????????catch?(ClassNotFoundException?e)
?37
????????{
?38
????????????e.printStackTrace();
?39
????????}
?40
????String?url="jdbc:odbc:[datebase]";????????????????//[datebase]為你的數(shù)據(jù)庫名
?41
????try?{
?42
?????????conn=?DriverManager.getConnection(url,user,password);
?43
????????}?catch?(SQLException?e)
?44
????????{
?45
????????????e.printStackTrace();
?46
????????}
?47
????????}
?48
*/
?49
?50
/**//*
?51
////////////////////////Oracle8/8i/9i數(shù)據(jù)庫(thin模式)
?52
?53
????public?DBO()
?54
????{
?55
????try?{
?56
????????????Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
?57
????????}
?58
????????catch?(InstantiationException?e)
?59
????????{
?60
????????????e.printStackTrace();
?61
????????}
?62
????????catch?(IllegalAccessException?e)
?63
????????{
?64
????????????e.printStackTrace();
?65
????????}
?66
????????catch?(ClassNotFoundException?e)
?67
????????{
?68
????????????e.printStackTrace();
?69
????????}
?70
????????String?url="jdbc:oracle:thin:@localhost:[xxxx]:[datebase]";
?71
????????????????????????????????????????????????????????//[xxxx]為您的數(shù)據(jù)庫服務(wù)器端口(默認1521);[datebase]為你的數(shù)據(jù)庫名?
?72
????????try?{
?73
????????conn=?DriverManager.getConnection(url,user,password);
?74
????????}?catch?(SQLException?e)
?75
????????{
?76
????????????e.printStackTrace();
?77
????????}
?78
????}
?79
*/
?80
?81
?82
/**//*
?83
?84
//////////////////////////連接DB2數(shù)據(jù)庫
?85
public?DBO()
?86
????{
?87
????try?{
?88
????????????Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();
?89
????????}
?90
????????catch?(InstantiationException?e)
?91
????????{
?92
????????????e.printStackTrace();
?93
????????}
?94
????????catch?(IllegalAccessException?e)
?95
????????{
?96
????????????e.printStackTrace();
?97
????????}
?98
????????catch?(ClassNotFoundException?e)
?99
????????{
100
????????????e.printStackTrace();
101
????????}
102
????????String?url="jdbc:db2://localhost:[xxxx]/[datebase]";
103
????????????????????????????????????????????????????????//[xxxx]為您的數(shù)據(jù)庫服務(wù)器端口(默認5000);[datebase]為你的數(shù)據(jù)庫名?
104
????try?{
105
????????conn=?DriverManager.getConnection(url,user,password);?
106
????????}
107
????????catch?(SQLException?e)
108
????????{
109
????????????e.printStackTrace();
110
????????}
111
????}
112
113
*/
114
115
/**//*
116
117
//////////////////////////Sql?Server7.0/2000數(shù)據(jù)庫
118
public?DBO()
119
????{
120
????try?{
121
????????????Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();?
122
????????}
123
????????catch?(InstantiationException?e)
124
????????{
125
????????????e.printStackTrace();
126
????????}
127
????????catch?(IllegalAccessException?e)
128
????????{
129
????????????e.printStackTrace();
130
????????}
131
????????catch?(ClassNotFoundException?e)
132
????????{
133
????????????e.printStackTrace();
134
????????}
135
????????String?url="jdbc:microsoft:sqlserver://localhost:[xxxx];DatabaseName=[datebase]";
136
????????????????????????????????????????????????//[xxxx]為您的數(shù)據(jù)庫服務(wù)器的端口(默認1433);[datebase]為你的數(shù)據(jù)庫名??
137
????try?{
138
????????conn=?DriverManager.getConnection(url,user,password);
139
????????}?catch?(SQLException?e)
140
????????{
141
????????????e.printStackTrace();
142
????????}
143
????}
144
145
*/
146
147
148
/**//*
149
//////////////////////////Sybase數(shù)據(jù)庫?
150
151
public?DBO()
152
????{
153
????try?{
154
????????Class.forName("com.sybase.jdbc.SybDriver").newInstance();?
155
????????}
156
????????catch?(InstantiationException?e)
157
????????{
158
????????????e.printStackTrace();
159
????????}
160
????????catch?(IllegalAccessException?e)
161
????????{
162
????????????e.printStackTrace();
163
????????}
164
????????catch?(ClassNotFoundException?e)
165
????????{
166
????????????e.printStackTrace();
167
????????}
168
????????String?url?="?jdbc:sybase:Tds:localhost:[xxxx]/[datebase]";????
169
????????????????????????????????????????????????????//[xxxx]為您的數(shù)據(jù)庫服務(wù)器的端口(默認5007);[datebase]為你的數(shù)據(jù)庫名
170
????????Properties?SysProps?=?System.getProperties();
171
????????SysProps.put("user","[username]");?????????????//[username]為您連接數(shù)據(jù)庫的用戶名
172
????????SysProps.put("password","[password]");????????//[password]為您連接數(shù)據(jù)庫的密碼
173
????try?{
174
????????conn=?DriverManager.getConnection(url,?SysProps);
175
????????}?catch?(SQLException?e)
176
????????{
177
????????????e.printStackTrace();
178
????????}
179
????}
180
*/
181
182
/**//*
183
//////////////////////////Informix數(shù)據(jù)庫
184
????public?DBO()
185
????{
186
????try?{
187
????????Class.forName("com.informix.jdbc.IfxDriver").newInstance();?
188
????????}
189
????????catch?(InstantiationException?e)
190
????????{
191
????????????e.printStackTrace();
192
????????}
193
????????catch?(IllegalAccessException?e)
194
????????{
195
????????????e.printStackTrace();
196
????????}
197
????????catch?(ClassNotFoundException?e)
198
????????{
199
????????????e.printStackTrace();
200
????????}
201
????????String?url="jdbc:informix-sqli://123.45.67.89:[xxxx]/[datebase]:INFORMIXSERVER=myserver;user=[username];password=[password]";?
202
????????????????????????????????????????????????//[xxxx]為您的數(shù)據(jù)庫服務(wù)器的端口(默認1533);[datebase]為您的數(shù)據(jù)庫名??
203
????try?{
204
????????conn=?DriverManager.getConnection(url);?
205
????????}?catch?(SQLException?e)
206
????????{
207
????????????e.printStackTrace();
208
????????}
209
????}
210
211
*/
212
213
/**//*
214
//////////////////////////MySQL數(shù)據(jù)庫
215
216
????public?DBO()
217
????{
218
????try?{
219
????????Class.forName("org.gjt.mm.mysql.Driver").newInstance();
220
????????}
221
????????catch?(InstantiationException?e)
222
????????{
223
????????????e.printStackTrace();
224
????????}
225
????????catch?(IllegalAccessException?e)
226
????????{
227
????????????e.printStackTrace();
228
????????}
229
????????catch?(ClassNotFoundException?e)
230
????????{
231
????????????e.printStackTrace();
232
????????}
233
????????String?url="jdbc:mysql://localhost/[datebase]?user=[username]&password=[password]&useUnicode=true&characterEncoding=[CharCoding]";
234
????????????????????????????????????????????????????//[CharCoding]為您的數(shù)據(jù)庫服務(wù)器使用的語言編碼(默認8859-1);[datebase]為您的數(shù)據(jù)庫名??
235
236
????try?{
237
????????conn=?DriverManager.getConnection(url);?
238
????????}?catch?(SQLException?e)
239
????????{
240
????????????e.printStackTrace();
241
????????}
242
????}
243
*/
244
245
/**//*
246
//////////////////PostgreSQL數(shù)據(jù)庫
247
248
249
????public?DBO()
250
????{
251
????try?{
252
????????Class.forName("org.postgresql.Driver").newInstance();
253
????????}
254
????????catch?(InstantiationException?e)
255
????????{
256
????????????e.printStackTrace();
257
????????}
258
????????catch?(IllegalAccessException?e)
259
????????{
260
????????????e.printStackTrace();
261
????????}
262
????????catch?(ClassNotFoundException?e)
263
????????{
264
????????????e.printStackTrace();
265
????????}
266
????????String?url?="jdbc:postgresql://localhost/[datebase]";
267
????????????????????????????????????????????????//[datebase]為您的數(shù)據(jù)庫名??
268
????try?{
269
????????conn=?DriverManager.getConnection(url,user,password);?
270
????????}?catch?(SQLException?e)
271
????????{
272
????????????e.printStackTrace();
273
????????}
274
????}
275
276
*/
277
278
}
279