熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

數據庫連接池java實現小結

2022-06-13   來源: Java核心技術 

   因為工作需要要使用到連接池所以拜讀了互聯網上眾多前輩的文章學了不少經驗這裡想做一個小結加上自己的想法和在一起希望能給大家一些幫助
  
  目的
  消除數據庫頻繁連接帶來的開銷和瓶頸
  解決方案
  不過多的限制用戶的使用既不能太多的要求用戶按規定的方法得到和使用數據庫連
  盡量保持用戶的習慣
  目前的很多方法都是要求用戶只能按規定方法使用連接不能使用直接關閉數據連接的方法解決辦法就是使用代理類來中間解決可以參考html
  
  能維護連接的正常狀態
  因為針對數據庫連接創建的資源如果不能及時的釋放就會影響下一次數據連接的使用例如在sql k中一個連接不同創建多條Statement否則操作時會有數據連接占線的異常所以必須在歸還連接以後釋放這些資源
  
  
   //判斷是使用了createStatement語句 if (CREATESTATEequals(methodgetName())) { obj = methodinvoke(conn args); statRef = (Statement)obj;//記錄語句 return obj; }
  
  
  
  
   //判斷是否調用了close的方法如果調用close方法則把連接置為無用狀態 if(CLOSEequals(methodgetName())) { //設置不使用標志 setIsFree(false); //檢查是否有後續工作清除該連接無用資源 if (statRef != null) statRefclose(); if (prestatRef != null) prestatRefclose(); return null; }
  
  
  
  正確保護類不被違例使用
  一個考慮就是不能讓用戶隨便使用代理類而只能自己使用一個就是用內部私有類一個就是使用只有指定類才能調用的標志我的實現就是采用後者
  
   /** * 創建連接的工廠只能讓工廠調用 * @param factory 要調用工廠並且一定被正確初始化 * @param param 連接參數 * @return 連接 */ static public _Connection getConnection(ConnectionFactory factory ConnectionParam param) { if (factoryisCreate())//判斷是否正確初始化的工廠 { _Connection _conn = new _Connection(param); return _conn; } else return null; }
  
  
  提供良好的用戶接口簡單實用
  使用靜態方法創建工廠然後來得到連接使用完全和普通的Connection方法一樣沒有限制同時為了方便設置了連接參數類和工廠參數類
  
   ConnectionParam param = new ConnectionParam(driverurluserpassword); ConnectionFactory cf = null;//new ConnectionFactory(param new FactoryParam()); try{ cf = new ConnectionFactory(paramnew FactoryParam()); Connection conn = cfgetFreeConnection(); Connection conn = cfgetFreeConnection(); Connection conn = cfgetFreeConnection(); Statement stmt = conncreateStatement(); ResultSet rs = stmtexecuteQuery(select * from requests); if (rsnext()) { Systemoutprintln(conn y); } else { Systemoutprintln(conn n); } stmtclose(); connclose();
  
  
  為了實現連接池的正常運作使用了單態模
   /** * 使用指定的參數創建一個連接池 */ public ConnectionFactory(ConnectionParam param FactoryParam fparam) throws SQLException { //不允許參數為空 if ((param == null)||(fparam == null)) throw new SQLException(ConnectionParam和FactoryParam不能為空); if (m_instance == null) { synchronized(ConnectionFactoryclass){ if (m_instance == null) { //new instance //參數定制 m_instance = new ConnectionFactory(); nnparam = param; m_instanceMaxConnectionCount = fparamgetMaxConn(); m_instanceMinConnectionCount = fparamgetMinConn(); m_instanceManageType = fparamgetType(); m_instanceisflag = true; //初始化創建MinConnectionCount個連接 Systemoutprintln(connection factory 創建!); try{ for (int i=; i < m_instance.MinConnectionCount; i++) { _Connection _conn = _Connection.getConnection(m_instance, nnparam); if (_conn == null) continue; System.out.println("connection創建"); m_instance.FreeConnectionPool.add(_conn);//加入空閒連接池 m_instance.current_conn_count ++; //標志是否支持事務 m_instance.supportTransaction = _conn.isSupportTransaction(); } } catch(Exception e) { e.printStackTrace(); } //根據策略判斷是否需要查詢 if (m_instance.ManageType != 0) { Thread t = new Thread(new FactoryMangeThread(m_instance)); t.start(); } } } } }
  
  
  
  連接池的管理
  對於連接池的管理,我是設想使用靜態管理和動態管理兩種策略,設置了最大限制,和恆定的連接數。tW.wingwiT.COM使用了2個池,一個空閒池,一個使用池。靜態就是使用的時候發現空閒連接不夠再去檢查。動態就是使用了一個線程定時檢查。
  
   //根據策略判斷是否需要查詢 if (m_instance.ManageType != 0) { Thread t = new Thread(new FactoryMangeThread(m_instance)); t.start(); }
   //連接池調度線程public class FactoryMangeThread implements Runnable { ConnectionFactory cf = null; long delay = 1000; public FactoryMangeThread(ConnectionFactory obj) { cf = obj; } /* (non-Javadoc) * @see java.lang.Runnable#run() */ public void run() { while(true){ try{ Thread.sleep(delay); } catch(InterruptedException e){} System.out.println("eeeee"); //判斷是否已經關閉了工廠,那就退出監聽 if (cf.isCreate()) cf.schedule(); else System.exit(1); } }}
  
  
  
  最後給出完整的源代碼:
  
  
  
  --------------------------------------------------------------------------------
  
  
  _Connectio.java
  
  package nnectionpool;
  import java.lang.reflect.*;import java.sql.*;
  /** * @author youyongming * 定義數據庫連接的代理類 */public class _Connection implements InvocationHandler { //定義連接 private Connection conn = null; //定義監控連接創建的語句 private Statement statRef = null; private PreparedStatement prestatRef = null; //是否支持事務標志 private boolean supportTransaction = false; //數據庫的忙狀態 private boolean isFree = false; //最後一次訪問時間 long lastAccessTime = 0; //定義要接管的函數的名字 String CREATESTATE = "createStatement"; String CLOSE = "close"; String PREPARESTATEMENT = "prepareStatement"; String COMMIT = "commit"; String ROLLBACK = "rollback";
   /** * 構造函數,采用私有,防止被直接創建 * @param param 連接參數 */ private _Connection(ConnectionParam param) { //記錄日至 try{ //創建連接 Class.forName(param.getDriver()).newInstance(); conn = DriverManager.getConnection(param.getUrl(),param.getUser(), param.getPassword()); DatabaseMetaData dm = null; dm = conn.getMetaData(); //判斷是否支持事務 supportTransaction = dm.supportsTransactions(); } catch(Exception e) { e.printStackTrace(); } }
   /* (non-Javadoc) * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; //判斷是否調用了close的方法,如果調用close方法則把連接置為無用狀態 if(CLOSE.equals(method.getName())) { //設置不使用標志 setIsFree(false); //檢查是否有後續工作,清除該連接無用資源 if (statRef != null) statRef.close(); if (prestatRef != null) prestatRef.close(); return null; } //判斷是使用了createStatement語句 if (CREATESTATE.equals(method.getName())) { obj = method.invoke(conn, args); statRef = (Statement)obj;//記錄語句 return obj; } //判斷是使用了prepareStatement語句 if (PREPARESTATEMENT.equals(method.getName())) { obj = method.invoke(conn, args); prestatRef = (PreparedStatement)obj; return obj; } //如果不支持事務,就不執行該事物的代碼 if ((COMMIT.equals(method.getName())||ROLLBACK.equals(method.getName())) && (!isSupportTransaction())) return null; obj = method.invoke(conn, args); //設置最後一次訪問時間,以便及時清除超時的連接 lastAccessTime = System.currentTimeMillis(); return obj; }
   /** * 創建連接的工廠,只能讓工廠調用 * @param factory 要調用工廠,並且一定被正確初始化 * @param param 連接參數 * @return 連接 */ static public _Connection getConnection(Connec
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26787.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.