c3p0的用法

 一、下載
從SourceForge 網站下載最新的版本 
http://sourceforge.net/projects/c3p0/

二、快速體驗
把這一個文件lib/c3p0-0.9.1-pre9.jar複製到你的  CLASSPATH即可。

import com.mchange.v2.c3p0.*; 
... 
ComboPooledDataSource cpds = new ComboPooledDataSource(); 
cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" ); 
cpds.setUser("dbuser"); 
cpds.setPassword("dbpassword"); 
你還可以設置如下參數
cpds.setMaxStatements( 180 ); 
然後你就可以從cpds.getConnection()獲得連接了。

最後,執行下面語句銷燬cpds.
DataSources.destroy( cpds ); 

三、建立自定義連接池工廠
爲了適應有多個數據源的單一系統,現在定義在這個系統中使用key字符串來識別每一個數據源,如
oa - 識別 OA 系統
epr - 識別 ERP 系統
hr - 識別 HR 系統
等等
詳細代碼與註釋如下:
///////////////////////////////////////////////////////////////
package com.paipaiestore.database.c3p0;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.DataSources;
/**
 * 數據連接池工廠 
 * @author samland
 * @version 1.0, 2006-11
 */
public class DBPoolFactory {

 private static DBPoolFactory dbpoolFactory = new DBPoolFactory();
 /**
  * 連接池列表
  */
 private static Map poollist = new HashMap();

 private DBPoolFactory(){
  
 }
 
 public static DBPoolFactory getInstance(){
  return dbpoolFactory;
 }
 /**
  * 向連接池列表添加一個新的池化(Pooled)數據源
  * @param key 
  * @param configFile 配置文件名。爲了簡化參數輸入與便於外部維護,可以把配置好的文件傳入這裏分析
  */
 public void add(String key, String configFile) {
  //read config from file, and build a dbpool
 }
 /**
  * 向連接池列表添加一個新的池化(Pooled)數據源
  * @param key
  * @param driver 數據連接驅動,如com.mysql.jdbc.Driver
  * @param url 連接串, 如jdbc:mysql://localhost/samland
  * @param username 數據庫連接用戶名,如samland
  * @param password 數據庫連接用戶密碼
  * @throws Exception
  */
 public void add(String key, String driver, String url, String username, String password) 
  throws Exception{
  if (key==null) throw new Exception("DBPool 'key' CANNOT be null") ;
  
  Class.forName(driver);
  DataSource ds_unpooled = DataSources.unpooledDataSource(url, username, password); 
  DataSource ds_pooled = DataSources.pooledDataSource( ds_unpooled );
  if (poollist.containsKey(key)){
   poollist.remove(key); 
  }
  poollist.put(key, ds_pooled);
 }
 /**
  * 根據key字符串獲取連接池
  * @param key
  * @return DBPool 連接池
  * @throws Exception
  */
 public DBPool getDBPool(String key) throws Exception{
  if (key==null) throw new Exception("DBPool 'key' CANNOT be null") ;
  DataSource ds = (DataSource)poollist.get(key);
  DBPool dbpool = new DBPool();
  dbpool.setDs_pooled(ds);
  return dbpool;
 }

}
///////////////////////////////////////////////////////////////

四、連接池的使用
通過DBPool來獲取數據庫連接 (jdbc connection)。
4.1 由DBPoolFactory工廠產生一個DBPool
4.2 同時,DBPoolFactory工廠根據傳入的參數key向這個DBPool注入數據源
4.3 從DBPool產生線程內的Connection
///////////////////////////////////////////////////////////////
package com.paipaiestore.database.c3p0;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

public class DBPool {
 /**
  * 數據庫連接。同一個線程使用同一個連接。
  */
 protected static ThreadLocal connection = new ThreadLocal();
 /**
  * 數據源,需由DBPoolFactory工廠注入
  */
 private DataSource ds_pooled;

 /**
  * 不能獨立構造,必須從DBPoolFactory工廠產生
  */
 protected DBPool(){}
 
 /**
  * get 數據源
  * @return
  */
 public DataSource getDs_pooled() {
  return ds_pooled;
 }

 /**
  * 注入數據源
  * @param ds_pooled
  */
 public void setDs_pooled(DataSource ds_pooled) {
  this.ds_pooled = ds_pooled;
 }

 /**
  * 獲得數據庫連接
  * 同一個線程只返回相同的一個連接。
  * @return Connection
  * @throws SQLException
  */
 public Connection getConnection() throws SQLException{
  Connection con = (Connection)connection.get();
  if (con==null) {
   con = ds_pooled.getConnection();
   connection.set(con);
  }
  return con;
 }
}
///////////////////////////////////////////////////////////////

五、改進線程內數據庫連接的使用
爲了適應程序已經使用開的jdbc事務管理,因此需要改進DBPool成爲Transaction類,
而原來的DBPool則縮減爲如下代碼:
///////////////////////////////////////////////////////////////
public class DBPool {
 private DataSource ds_pooled;
 protected DBPool(){}
 public DataSource getDs_pooled() {
  return ds_pooled;
 }
 public void setDs_pooled(DataSource ds_pooled) {
  this.ds_pooled = ds_pooled;
 }
}
///////////////////////////////////////////////////////////////
package com.paipaiestore.database.c3p0;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

public class Transaction {
 /**
  * 數據庫連接。同一個線程使用同一個連接。
  */
 protected static ThreadLocal connection = new ThreadLocal();
 protected static boolean isInUsed = false;
 /**
  * 開始一個事務
  * 如果當前線程的數據庫連接不存在,則會新獲得一個數據庫連接
  * @param key 
  * @throws Exception
  */
 public static void beginTransaction(String key) throws Exception{
  Connection conn = (Connection)connection.get();
  if (conn==null) {
   conn = createConnection(key);
            setConnection(conn);
  }
  conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
        conn.setAutoCommit(false);
        isInUsed = true;
 }
 /**
  * 提交一個事務
  * @throws SQLException
  */
 public static void commitTransaction() throws SQLException {
   Connection conn = (Connection)connection.get();
   conn.commit();
 }
 /**
  * 回滾一個事務
  * @throws SQLException
  */
 public static void rollbackTransaction() throws SQLException {
   Connection conn = (Connection)connection.get();
   conn.rollback();
 }
 public static boolean getIsInUsed() {
  return isInUsed;
 } 
 private static void closeConnection() {
  try {
   Connection conn = (Connection)connection.get();
   if (conn!=null) {
    connection.set(null);
    conn.close();
   }
  }catch(SQLException sqlexception) { 
   
  }
 } 
 private static void close(ResultSet rs){
  try
        {
            Statement st = rs.getStatement();
            Connection conn = st.getConnection();
            rs.close();
            st.close();
            conn.close();
        }
        catch(Exception exception) { }
 } 
 /**
  * 獲得數據庫連接
  * 同一個線程只返回相同的一個連接。
  * @return
  * @throws SQLException
  */
 public static Connection getConnection() throws SQLException {
        Connection conn = null;
        conn = (Connection)connection.get();
        if(conn == null)
            throw new NullPointerException();
        else
            return conn;
    } 
 
 private static void setConnection(Connection conn){
  connection.set(conn);
 } 
 /**
  * 獲得一個新的數據庫連接
  * @param key
  * @return Connection
  * @throws Exception
  */
 private static Connection createConnection(String key)
  throws Exception  {
  DBPoolFactory df = DBPoolFactory.getInstance();
  DataSource ds_pooled = df.getDBPool(key).getDs_pooled() ;
  Connection conn = ds_pooled.getConnection();
  df = null;
        return conn;
    }
}
///////////////////////////////////////////////////////////////
六、測試
///////////////////////////////////////////////////////////////
package samland;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.paipaiestore.database.c3p0.DBPoolFactory;
import com.paipaiestore.database.c3p0.Transaction;

public class TestTransaction {
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  DBPoolFactory df = DBPoolFactory.getInstance();
  
  Connection con  = null;
  Statement  stmt = null;
  ResultSet  rs   = null;
  try {
   df.add("jxc","com.mysql.jdbc.Driver","jdbc:mysql://paipaiestore.com/samland","samland","*****");
   
   Transaction.beginTransaction("samland");
   con = Transaction.getConnection();
   stmt = con.createStatement();
   rs = stmt.executeQuery("SELECT * FROM users");
   while (rs.next())
   {
    System.out.print( rs.getString(1) );
    System.out.print( rs.getString(2) );
    System.out.println( rs.getString(3) );
   }
   Transaction.commitTransaction();
   df = null;
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章