自己做數(shù)據(jù)庫連接池c3p0
如何快速使用c3p0 - JDBC3 Connection and Statement Pooling 一、下載 從SourceForge 網(wǎng)站下載最新的版本 http:///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"); 你還可以設置如下參數(shù) cpds.setMaxStatements( 180 ); 然后你就可以從cpds.getConnection()獲得連接了。
最后,執(zhí)行下面語句銷毀cpds. DataSources.destroy( cpds );
三、建立自定義連接池工廠 為了適應有多個數(shù)據(jù)源的單一系統(tǒng),現(xiàn)在定義在這個系統(tǒng)中使用key字符串來識別每一個數(shù)據(jù)源,如 oa - 識別 OA 系統(tǒng) epr - 識別 ERP 系統(tǒng) hr - 識別 HR 系統(tǒng) 等等 詳細代碼與注釋如下: /////////////////////////////////////////////////////////////// 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; /** * 數(shù)據(jù)連接池工廠 * @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)數(shù)據(jù)源 * @param key * @param configFile 配置文件名。為了簡化參數(shù)輸入與便于外部維護,可以把配置好的文件傳入這里分析 */ public void add(String key, String configFile) { //read config from file, and build a dbpool } /** * 向連接池列表添加一個新的池化(Pooled)數(shù)據(jù)源 * @param key * @param driver 數(shù)據(jù)連接驅(qū)動,如com.mysql.jdbc.Driver * @param url 連接串, 如jdbc:mysql://localhost/samland * @param username 數(shù)據(jù)庫連接用戶名,如samland * @param password 數(shù)據(jù)庫連接用戶密碼 * @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); } /** * 根據(jù)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來獲取數(shù)據(jù)庫連接 (jdbc connection)。 4.1 由DBPoolFactory工廠產(chǎn)生一個DBPool 4.2 同時,DBPoolFactory工廠根據(jù)傳入的參數(shù)key向這個DBPool注入數(shù)據(jù)源 4.3 從DBPool產(chǎn)生線程內(nèi)的Connection /////////////////////////////////////////////////////////////// package com.paipaiestore.database.c3p0;
import java.sql.Connection; import java.sql.SQLException;
import javax.sql.DataSource;
public class DBPool { /** * 數(shù)據(jù)庫連接。同一個線程使用同一個連接。 */ protected static ThreadLocal connection = new ThreadLocal(); /** * 數(shù)據(jù)源,需由DBPoolFactory工廠注入 */ private DataSource ds_pooled;
/** * 不能獨立構造,必須從DBPoolFactory工廠產(chǎn)生 */ protected DBPool(){} /** * get 數(shù)據(jù)源 * @return */ public DataSource getDs_pooled() { return ds_pooled; }
/** * 注入數(shù)據(jù)源 * @param ds_pooled */ public void setDs_pooled(DataSource ds_pooled) { this.ds_pooled = ds_pooled; }
/** * 獲得數(shù)據(jù)庫連接 * 同一個線程只返回相同的一個連接。 * @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; } } ///////////////////////////////////////////////////////////////
五、改進線程內(nèi)數(shù)據(jù)庫連接的使用 為了適應程序已經(jīng)使用開的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 { /** * 數(shù)據(jù)庫連接。同一個線程使用同一個連接。 */ protected static ThreadLocal connection = new ThreadLocal(); protected static boolean isInUsed = false; /** * 開始一個事務 * 如果當前線程的數(shù)據(jù)庫連接不存在,則會新獲得一個數(shù)據(jù)庫連接 * @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) { } } /** * 獲得數(shù)據(jù)庫連接 * 同一個線程只返回相同的一個連接。 * @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); } /** * 獲得一個新的數(shù)據(jù)庫連接 * @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(); } } } ///////////////////////////////////////////////////////////////
未經(jīng)嚴格測試,請使用者提出修改意見。
下一步需要增加檢測當前連接池狀態(tài)的功能。
|