Java開發筆記(一百五十)C3P0鏈接池的用法

JDBC既制定統一標準兼容了多種數據庫,又利用預報告堵上了SQL注入漏洞,照理說已經很完善了,但是人算不如天算,它在性能方面不盡如人意。問題出在數據庫鏈接的管理上,按照正常流程,每次操做完數據庫,都要關閉鏈接,不管是代碼裏手工關閉,仍是由try語句自動關閉。若是沒有及時關閉數據庫鏈接,就會長時間佔用有限的數據庫內存,導致無謂的系統資源浪費。然而頻繁開關數據庫鏈接也有毛病,由於每次獲取操做都要CPU處理,常常鏈接數據庫會加劇CPU的負擔。看來內存與CPU像是一對難兄難弟,無論怎麼作都會影響其中一個,正所謂魚與熊掌不可兼得。
其實鏈接跟線程的狀況類似,線程也很頭疼頻繁建立致使的資源開銷,爲此Java早早就設計了線程池機制,事先在一個池子中容納若干線程,須要使用線程時便從中挑一根線程執行任務,任務作完再歸還線程,如此實現了線程資源的循環利用,有效提升了系統的總體運行效率。既然線程們組建了線程池這個你們庭,那麼鏈接們可否也組成鏈接池的你們庭呢?Java當然自帶了線程池工具,卻未能推出相似的鏈接池工具,因而各類第三方的鏈接池蜂擁而起,例如DBCP、C3P0、Proxool等等,其中應用普遍的當數C3P0。
C3P0是一個開源的數據庫鏈接池,它支持JDBC3規範和JDBC2的標準擴展。若要在Java工程中運用C3P0,得先導入它的jar包,好比c3p0-0.9.5.4.jar,同時還要導入該jar包依賴的mchange-commons-java-0.2.16.jar,也就是一共導入兩個jar文件。使用C3P0很簡單,掌握ComboPooledDataSource類的用法就夠了,該類的常見方法說明以下:
setDriverClass:設置鏈接池的數據庫驅動。
setJdbcUrl:設置數據庫的鏈接地址。
setUser:設置數據庫的用戶名。
setPassword:設置數據庫的密碼。
setMaxPoolSize:設置鏈接池大小的上限。
setMinPoolSize:設置鏈接池大小的下限。
setInitialPoolSize:設置鏈接池的初始大小。
setMaxStatements:設置報告的最大個數。
setCheckoutTimeout:設置獲取鏈接的等待時間,單位毫秒。當鏈接池中的全部鏈接都被佔用的時候,新請求想獲取鏈接就必須等待,等待現有鏈接被釋放後才能獲取空閒鏈接。默認爲0表示一直等待下去。
setMaxIdleTime:設置最大空閒時間,單位秒。若是某個鏈接超過該時間仍未使用,則會被自動回收。默認爲0表示不判斷是否超時,也就是永不回收。
getConnection:從鏈接池中獲取一個鏈接。
close:關閉鏈接池。
引入鏈接池以後,完整的數據庫操做流程分解成了兩大步驟:初始化鏈接池、從鏈接池中取出一個鏈接處理,下面分別予以介紹。
一、初始化鏈接池
該步驟首先建立C3P0鏈接池的對象,再依次調用相關方法設置詳細的參數信息,包括數據庫驅動、鏈接地址、用戶名、密碼,以及與鏈接池有關的規格參數。下面是初始化C3P0鏈接池的代碼例子:html

	private static ComboPooledDataSource dataSource; // 聲明C3P0鏈接池的對象
	// 初始化鏈接池
	private static void initDataSource() {
		dataSource = new ComboPooledDataSource(); // 建立C3P0鏈接池
		try {
			dataSource.setDriverClass(driver_class); // 設置鏈接池的數據庫驅動
		} catch (PropertyVetoException e) {
			e.printStackTrace();
		}
		dataSource.setJdbcUrl(dbUrl); // 設置數據庫的鏈接地址
		dataSource.setUser(dbUserName); // 設置數據庫的用戶名
		dataSource.setPassword(dbPassword); // 設置數據庫的密碼
		dataSource.setMaxPoolSize(10); // 設置鏈接池大小的上限
		dataSource.setMinPoolSize(1); // 設置鏈接池大小的下限
		dataSource.setInitialPoolSize(3); // 設置鏈接池的初始大小
	}

  

二、從鏈接池中取出一個鏈接處理
除了一開始調用鏈接池的getConnection獲取鏈接以外,該步驟剩餘的操做過程與JDBC原有流程保持一致,即得到數據庫鏈接以後,一樣要建立鏈接的報告,而後命令報告執行SQL語句。下面是經過鏈接池操做數據庫的代碼例子:java

	// 顯示性別分組
	private static void showRecordGroupBySex() {
		String sql = "select sex,count(1) count from teacher group by sex order by sex asc";
		// 從鏈接池中獲取鏈接、建立鏈接的報告、命令報告執行指定的SQL語句
		try (Connection conn = dataSource.getConnection();
				Statement stmt = conn.createStatement();
				ResultSet rs = stmt.executeQuery(sql)) {
			while (rs.next()) { // 循環遍歷結果集裏面的全部記錄
				int sex = rs.getInt("sex"); // 獲取指定字段的整型值
				int count = rs.getInt("count"); // 獲取指定字段的整型值
				String desc = String.format("%s老師有%d位;", sex==0 ? "男" : "女", count);
				System.out.print(desc);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

 

整合鏈接池的初始化和具體操做的代碼,運行包含整合代碼以內的測試程序,觀察以下日誌可知C3P0鏈接池正常工做。sql

男老師有2位;女老師有3位;  



更多Java技術文章參見《Java開發筆記(序)章節目錄數據庫

相關文章
相關標籤/搜索