程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java中自定義數據庫連接池

java中自定義數據庫連接池

編輯:關於JAVA

連接池是非常好的想法,應用很普遍。自己寫一個數據庫連接池,並不像想象中那樣困難。一般系統對連接池的功能不會有太多要求,使用自己的連接池未必是個壞主意。下面以Oracle為例,但是對Teradata和Greenplum也是可行的。另外我還實現了連接有效性檢查(checkConn)和恢復連接(resetConn)的方法。本例編程采用的是JRE1.4.2環境(別忘了准備訪問數據庫的jar包)。有任何問題請隨時留言,歡迎探討。

在Oracle內創建測試數據:

drop table my_table;     
create table my_table(     
       field_id varchar2(3),     
       field_content varchar2(60),     
       record_create_date date default sysdate     
);     
        
insert into my_table(field_id,field_content) values('001','this is first record');     
insert into my_table(field_id,field_content) values('002','this is second record');     
insert into my_table(field_id,field_content) values('003','this is third record');     
commit;

DBPool.java:

package dataWebService;     
        
import java.sql.DriverManager;     
import java.util.Date;     
import java.sql.Connection;     
import java.sql.SQLException;     
import java.sql.Statement;     
        
public class DBPool{     
    private String cls;     
    private String url;     
    private String usr;     
    private String pss;      
    private int connCount = 3;//連接數     
    private Connection[] connections;//保存數據庫連接     
    private String[] connStatus;// 已連可用Y   已連不可用N   未連接X     
    private Date[] lastQueryTime;//時間戳     
             
    public DBPool(DBPoolConfiguration poolConfiguration){     
        this.connCount=poolConfiguration.getConnCount();     
        this.cls=poolConfiguration.getCls();     
        this.url=poolConfiguration.getUrl();     
        this.usr=poolConfiguration.getUsr();     
        this.pss=poolConfiguration.getPss();     
        this.connections=new Connection[this.connCount];     
        this.connStatus=new String[this.connCount];     
        for(int i=0;i<this.connCount;i++){     
            this.connStatus[i]="X";//初始化全部未連接     
        }     
        this.lastQueryTime = new Date[this.connCount];           
    }     
             
    public DBPool(String cls,String url,String usr,String pss){     
        this.cls=cls;     
        this.url=url;     
        this.usr=usr;     
        this.pss=pss;     
        this.connections=new Connection[this.connCount];     
        this.connStatus=new String[this.connCount];     
        for(int i=0;i<this.connCount;i++){     
            this.connStatus[i]="X";//初始化全部未連接     
        }     
        this.lastQueryTime = new Date[this.connCount];     
    }     
        
    public void initPool(){     
        if(connCount<1){     
            System.out.println("請正確設置連接池窗口個數");     
        }else{     
            try{     
                Class.forName(this.cls);//register class     
            }catch(ClassNotFoundException e){     
                System.out.println(e.getMessage());     
            }catch(Exception e){     
                System.out.println(e.getMessage());//other exceptions     
            }     
        
            for(int i=0;i<this.connCount;i++){     
                try{     
                    this.connections[i]=DriverManager.getConnection(this.url, this.usr, this.pss);     
                    this.connStatus[i]="Y";     
                }catch(SQLException e){     
                    System.out.println(e.getMessage());     
                }catch(Exception e){     
                    System.out.println(e.getMessage());//other exceptions     
                }     
            }        
            System.out.println("initPool is ready...");     
        }//end if     
    }     
        
    public void freePool(){     
        for(int i=0;i<this.connCount;i++){     
            try{     
                this.connections[i].commit();     
                this.connections[i].close();     
                this.connStatus[i]="X";     
                this.lastQueryTime[i]=null;     
            }catch(Exception e){     
                try{     
                    this.connections[i].close();     
                    this.connStatus[i]="X";     
                    this.lastQueryTime[i]=null;                      
                }catch(Exception e1){     
                    System.out.println(e1.getMessage());//just for catch     
                }     
            }                
        }     
        System.out.println("freePool is over ...");     
    }     
        
    public DBPoolConnection getPoolConn() throws DBPoolIsFullException{     
        DBPoolConnection poolConnection = new DBPoolConnection();     
        poolConnection.connNbr=getConnNbr();     
        if(poolConnection.connNbr==-1){     
            throw new DBPoolIsFullException("連接池已滿");     
        }else{     
            poolConnection.conn=getConn(poolConnection.connNbr);     
        }     
        return poolConnection;     
    }     
        
    public void freePoolConn(DBPoolConnection poolConnection){     
        if(poolConnection==null){     
            System.out.println("poolConnection==null,不需要釋放");     
        }else{     
            freeConn(poolConnection.connNbr);     
        }     
    }     
             
    public void printPoolStatus(){     
        for(int i=0;i<this.connStatus.length;i++){     
            System.out.println("");     
            System.out.print(this.connStatus[i].toString());     
            if(this.lastQueryTime[i]==null){     
                System.out.print("-[null] ");     
            }else{     
                System.out.print("-["+this.lastQueryTime[i].toString()+"] ");     
            }     
        }     
        System.out.println("");     
    }     
             
    public String getCls(){     
        return this.cls;     
    }     
        
    public String getUrl(){     
        return this.url;     
    }     
        
    public String getUsr(){     
        return this.usr;     
    }     
        
    int getConnNbr(){     
        int iConn=-1;     
        for(int i=0;i<this.connCount;i++){     
            if(this.connStatus[i].equals("Y")){     
                this.lastQueryTime[i]=new Date();     
                this.connStatus[i]="N";     
                iConn=i;     
                break;     
            }     
        }     
        return iConn;     
    }     
             
    Connection getConn(int i){     
        return this.connections[i];     
    }     
                 
    void closeConnForTest(DBPoolConnection poolConnection){     
        try{     
            this.connections[poolConnection.connNbr].close();     
        }catch(SQLException e){     
            System.out.println(e.getMessage());      
        }     
    }     
                 
    boolean checkConn(DBPoolConnection poolConnection){     
        Statement stmt=null;     
        String checkMessage="";     
        boolean checkResult=true;     
                 
        //檢查連接是否有效     
        try{     
            String sql = "select * from dual";     
            stmt = this.connections[poolConnection.connNbr].createStatement();     
            stmt.executeQuery(sql);//execute sql     
            stmt.close();     
            checkMessage = "checkConn:checkMessage:execute sql success";     
            System.out.println(checkMessage);     
        }catch(Exception e){     
            checkMessage = e.getMessage();     
            System.out.println(e.getMessage());//other exceptions     
            if(checkMessage==null){     
                checkMessage="e.getMessage() is null";     
                System.out.println(checkMessage);     
            }     
            //采取激進重連的策略,盡量避免業務中斷     
            if (checkMessage.indexOf("ORA-00942")>=0){     
                checkResult=true;//不需要重連     
            }else if(checkMessage.indexOf("does not exist")>=0){     
                checkResult=true;//不需要重連     
            }else if(checkMessage.indexOf("Syntax error")>=0){     
                checkResult=true;//不需要重連     
            }else{               
                checkResult=false;//需要重連     
            }     
        }     
        return checkResult;     
    }     
             
    boolean resetConn(DBPoolConnection poolConnection){     
        boolean result=false;//默認不需要重建連接      
                 
        if(poolConnection==null){     
            System.out.println("poolConnection==null,不知道您想重設哪個連接");     
        }else if(poolConnection.connNbr==-1){     
            System.out.println("poolConnection.connNbr==-1,不知道您想重設哪個連接");     
        }else{     
            if(checkConn(poolConnection)==true){     
                System.out.println("連接有效,不需要重設");     
            }else{     
                //重設連接     
                try{     
                    Class.forName(this.cls);//register class     
                }catch(ClassNotFoundException e){     
                    System.out.println(e.getMessage());     
                }catch(Exception e){     
                    System.out.println(e.getMessage());//other exceptions     
                }     
                try{     
                    this.connections[poolConnection.connNbr]=DriverManager.getConnection(this.url, this.usr, this.pss);     
                    this.connStatus[poolConnection.connNbr]="Y";     
                    System.out.println(poolConnection.connNbr+"連接已重建");     
                    result = true;//告知調用者連接已重建     
                }catch(SQLException e){     
                    System.out.println(e.getMessage());     
                }catch(Exception e){     
                    System.out.println(e.getMessage());//other exceptions     
                }        
            }     
        }     
        return result;     
    }     
                 
    void freeConn(int i){     
        try{     
            if(i==-1){     
                System.out.println("i=-1,不需要釋放");     
            }else{     
                this.connections[i].commit();     
            }     
        }catch(SQLException e){     
            System.out.println(e.getMessage());     
        }catch(Exception e){     
            System.out.println(e.getMessage());//other exceptions     
        }     
        this.connStatus[i]="Y";     
    }     
}

DBPoolConfiguration.java

package dataWebService;     
        
public class DBPoolConfiguration {     
    private String cls;     
    private String url;     
    private String usr;     
    private String pss;      
    private int connCount;//連接數      
             
    public String getCls() {     
        return cls;     
    }     
    public void setCls(String cls) {     
        this.cls = cls;     
    }     
    public String getUrl() {     
        return url;     
    }     
    public void setUrl(String url) {     
        this.url = url;     
    }     
    public String getUsr() {     
        return usr;     
    }     
    public void setUsr(String usr) {     
        this.usr = usr;     
    }     
    public String getPss() {     
        return pss;     
    }     
    public void setPss(String pss) {     
        this.pss = pss;     
    }     
    public int getConnCount() {     
        return connCount;     
    }     
    public void setConnCount(int connCount) {     
        this.connCount = connCount;     
    }     
}

DBPoolConnection.java:

package dataWebService;     
        
import java.sql.Connection;     
        
public class DBPoolConnection{     
    public int connNbr=-1;     
    public Connection conn=null;     
    DBPoolConnection(){     
        this.connNbr=-1;     
        this.conn = null;     
    }     
}

DBPoolIsFullException.java

package dataWebService;     
        
public class DBPoolIsFullException extends Exception{     
    static final long serialVersionUID=1L;     
    DBPoolIsFullException(String message){     
        super(message);     
    }     
}

Test.java

package myAction;     
        
import dataWebService.DBPool;     
import dataWebService.DBPoolConnection;     
import dataWebService.DBPoolConfiguration;     
import java.sql.ResultSet;     
import java.sql.ResultSetMetaData;     
import java.sql.Statement;     
        
public class Test {     
    static String rpad(String str,int len){     
        String s = str;     
        if(s==null){     
            s="";     
        }     
        while(s.getBytes().length<len){     
            s += " ";     
        }     
        return s;     
    }     
             
    public static void main(String[] args) {             
        //初始化     
        String cls ="",url="",usr="",pss="",sql="";     
        Statement stmt=null;     
        ResultSet rs=null;     
        String gapStr="|";//分隔符     
        int connCount=2;//最大連接數     
        
        //連接Oracle  配置     
        cls = "oracle.jdbc.driver.OracleDriver";     
        url = "jdbc:oracle:thin:@localhost:1521:myoradb";     
        usr = "abc";     
        pss = "123";     
                 
        sql = "select t.field_id,t.field_content,to_char(t.record_create_date,'YYYYMMDD') day from my_table t";     
        
        DBPoolConfiguration poolConfiguration=new DBPoolConfiguration();     
        poolConfiguration.setCls(cls);     
        poolConfiguration.setUrl(url);     
        poolConfiguration.setUsr(usr);     
        poolConfiguration.setPss(pss);     
        poolConfiguration.setConnCount(connCount);     
                 
        DBPool myPool = new DBPool(poolConfiguration);     
        myPool.initPool();     
        
                 
        System.out.println("");     
        System.out.print("after init Pool");     
        myPool.printPoolStatus();     
        System.out.println("");     
                 
        DBPoolConnection c1=null;     
        
        try{     
            c1 = myPool.getPoolConn();     
        
            System.out.println("");     
            System.out.print("after getPoolConn");     
            myPool.printPoolStatus();     
            System.out.println("");              
                     
            stmt = c1.conn.createStatement();     
            rs = stmt.executeQuery(sql);     
        
            ResultSetMetaData md = rs.getMetaData();     
                     
            String recordHead = "";     
            int colCount = md.getColumnCount();     
            for(int i=1;i<=colCount;i++){     
                if(recordHead.equals("")){     
                    recordHead += rpad(md.getColumnName(i),md.getColumnDisplaySize(i));     
                }else{     
                    recordHead+= gapStr + rpad(md.getColumnName(i),md.getColumnDisplaySize(i));     
                }     
            }     
            System.out.println(recordHead);//打印表頭     
                     
            while(rs.next()){     
                String tmp = "";     
                for(int i=1;i<=colCount;i++){     
                    int colSize = md.getColumnDisplaySize(i)>md.getColumnName(i).length()?md.getColumnDisplaySize(i):md.getColumnName(i).length();     
                    if(tmp.equals("")){     
                        tmp += rpad(rs.getString(i),colSize);     
                    }else{     
                        tmp += gapStr + rpad(rs.getString(i),colSize);     
                    }     
                }     
                System.out.println(tmp);//打印數據     
            }     
                     
            stmt.close();//釋放資源但是不關閉連接                           
            myPool.freePoolConn(c1);     
                     
            System.out.println("");     
            System.out.print("after freePoolConn");     
            myPool.printPoolStatus();     
            System.out.println("");              
        }catch(Exception e){     
            System.out.println(e.getMessage());     
        }     
        
        myPool.freePool();     
        
    }//end of main     
}

下面是Test.java的執行結果:

initPool is ready...     
        
after init Pool     
Y-[null]      
Y-[null]      
        
        
after getPoolConn     
N-[Wed Mar 20 14:46:31 GMT 2013]      
Y-[null]      
        
FIELD_ID|FIELD_CONTENT                                               |DAY          
001     |this is first record                                        |20130320 
002     |this is second record                                       |20130320 
003     |this is third record                                        |20130320 
        
after freePoolConn     
Y-[Wed Mar 20 14:46:31 GMT 2013]      
Y-[null]      
        
freePool is over ...

感謝您的耐心讀到此處,我相信接下去的文字會更有價值。

保持連接池簡單性的幾個設計思想(不一定正確):

1)在系統中連接池不應作為一個獨立的模塊,最好是作為某模塊的底層實現。這樣可以將超時管理、請求隊列、確保資源釋放、數據分頁(方言不可避免了)等功能剝離出去。

2)固定連接數比動態連接數容易實現,簡單的代碼更易於維護。

本例有待完善之處(供參考):

1)查詢空閒連接要遍歷數組,這樣當池中的連接數很大時可能會有問題(具體沒測過)

2)可以添加連接池阻塞的功能,有時候後台數據庫需要重啟,或者想重建連接池以提供更多的並發連接數?

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved