前面我們示範了一個簡單的資料庫連接配接池,我們再結合之前的mysql資料庫操作類MysqlHandler修改一下,實作一個使用連接配接池的mysql操作類。
首先,我們先得有一個自定義的異常類,貓哥主要想用它示範下抛出特定異常。
package sql;//Java中的類可以用不同的package(包)劃分,這樣更加條理
public class MysqlException extends Exception{//自定義異常類,因為繼承了Exception類,是以成為了異常家族的一員
public MysqlException(String msg){//構造函數,包含一條消息,此處我們簡單的以消息内容區分不同的資料庫異常
super(msg);
}
}
注意本篇中所有的類都是在package sql下的,也就是在包sql下。如果把類比做檔案,那包就是檔案夾——整理類的作用,如此而已。
OK,然後我們稍微改造下我們的資料庫連接配接池類如下:
package sql;
import java.sql.*;//這個java.sql和上面自定義的sql是一回事。名字都不一樣嘛,一個叫java.sql一個叫sql。就像李老四和李四是兩個人名。
import java.util.LinkedList;
public class MysqlPool {
//使用static保證全局共享一個池子,使用LinkedList是因為經常删除、添加元素
private static LinkedList pool = new LinkedList();
//最大連接配接數
private static int maxCount=20;
static{//此處修改為使用靜态代碼塊實作資料庫連接配接池初始化,注意靜态代碼塊中的語句隻會執行一次,且在類初始化時候執行
//下面的代碼無需捕獲異常,因為準備在MysqlHandler中捕獲資料庫異常
for(int i=0;i
MysqlHandler handler=new MysqlHandler();//此處借用MysqlHandler擷取資料庫連接配接,為啥借用?因為MysqlHandler幹這些事比較友善
//建立連接配接,并放于池中,不用擔心這個連接配接找不到了,因為已經是池中之物了
//此處應該注意,因為connection是要放入池中的,是以此處buildConnection建立的connection不用再依賴MysqlHandler類管理connection的釋放問題
Connection connection = handler.buildConnection();
pool.add(connection);//所有連接配接都非常保險的在pool中放置,随時可以取用
}
}
public static Connection getConnecton() throws MysqlException{//此處将異常抛出,在外面處理。也可以選擇在getConnecton内部處理,看程式員決策了
if(pool.size()==0)//配置設定完了
{
throw new MysqlException("資料庫連接配接池資源短缺,無連接配接可配置設定");
}
else{
return pool.remove(0);//删除第一個對象并傳回
}
}
public static void release(Connection connection){//使用完的歸還給池子
pool.add(connection);
}
}
需要注意兩點:1是靜态代碼塊的使用,讓整個程式不用再管理資料庫連接配接池的初始化問題,相對于手工init()初始化所有連接配接,靜态代碼塊在MysqlPool類第一次加載時自動調用顯得更加的牛X。2是注意我們使用MysqlHandler 的buildConnection方法拿到連接配接,這個方法沒有什麼變化,也沒有變化的必要,就是建立一個資料庫連接配接。
OK,再來看我們封裝的操作類:
package sql;
import java.sql.*;//導入資料庫相關類庫
/**
* MysqlHandler MySQL資料庫管理類,使用資料庫連接配接池
* @author 貓哥
* @date 2016.1.9
*/
public class MysqlHandler{
//依然是那熟悉的三個必備參數
private Connection conn = null;
private Statement stmt = null;
private ResultSet rs = null;
//建立資料庫連接配接,此處僅用于提供原始連接配接,供放入池中使用
public Connection buildConnection() {
String driver = "com.mysql.jdbc.Driver";//MySQL資料庫的驅動程式名
String url = "jdbc:mysql://localhost:3306/java?useUnicode=true&characterEncoding=utf-8";//資料庫連接配接字元串
String user = "root";//使用者名
String password = "Pass1234";//密碼
try{
Class.forName(driver);//加載驅動程式
conn=DriverManager.getConnection(url,user,password);//輸入必備參數,擷取連接配接
}
catch(Exception ex){
ex.printStackTrace();//可以輸出比較詳細的異常資訊
}
return conn;
}
//操作1,“增删改查”中,增、删、改都是執行sql語句,無需傳回ResultSet結果集,是以設定為一個方法
public int execute(String sql){
try {
conn=MysqlPool.getConnecton();//用時從池中取,很爽快
stmt=conn.createStatement();
int affectedCount = stmt.executeUpdate(sql);//此處真正執行stmt定義的操作
return affectedCount;//這個是收到影響的行數
}
catch(MysqlException myEx){//可以針對自定義的異常單獨處理
myEx.printStackTrace();
return -2;//傳回-2,表示資料庫連接配接池配置設定超限,可以在外面針對性處理,其實可以直接抛到更外層處理,還是看程式員決策了
}
catch (Exception ex) {
ex.printStackTrace();
return -1;//傳回-1,表示執行失敗了,有異常
}
}
//操作2,如果是查詢,需傳回結果集
public ResultSet query(String sql)throws Exception{
try{
conn=MysqlPool.getConnecton();//用時從池中取,很爽快
stmt=conn.createStatement();
rs = stmt.executeQuery(sql);//執行pstmt中定義的查詢
return rs;//将結果集傳回
}
catch(MysqlException myEx){//可以針對自定義的異常單獨處理
throw new MysqlException(myEx.getMessage());//還可以往外抛,可以針對查詢時資料庫連接配接池連接配接不足問題單獨處理(例如延遲響應使用者請求以下)
}catch(Exception ex){
ex.printStackTrace();
return null;
}
}
//操作3,釋放資源
public void sayGoodbye(){
//此處注意,conn在池中管理,此處無需關閉
if(rs!=null){//關閉結果集,這個不關閉也浪費
try {
rs.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
if(stmt!=null){//關閉Statement,不要浪費
try {
stmt.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
MysqlPool.release(conn);
}
}
OK,最後,單獨寫一個測試類,測試以下:
package sql;
import java.sql.*;
public class SqlTest {
public static void main(String[] args) throws Exception {//此處我們不處理異常
// TODO Auto-generated method stub
MysqlHandler hand=new MysqlHandler();
ResultSet rs=null;//可以使用多次
//查
rs=hand.query("select * from student_info");
//展示結果
System.out.println("\n查詢結果如下:");
while(rs.next()){
System.out.print(rs.getInt(1) + "|");
System.out.print(rs.getString(2) + "\t");
}
//增加2個
int addCount=hand.execute("insert into student_info (student_name) values('火星人'),('水星人')");
System.out.println("\n增加了"+addCount+"個");
//删除一個
int delCount=hand.execute("delete from student_info where student_name='張三'");
System.out.println("\n删除了"+delCount+"個");
//修改一個,把李四改造成火星人
int changeCount=hand.execute("update student_info set student_name='火星人李四' where student_name='李四'");
System.out.println("\n修改了"+changeCount+"個");
//查
rs=hand.query("select * from student_info");
System.out.println("\n查詢結果如下:");
while(rs.next()){
System.out.print(rs.getInt(1) + "|");
System.out.print(rs.getString(2) + "\t");
}
hand.sayGoodbye();
}
}