天天看點

Java Web簡明教程–Java篇[12]–使用連接配接池的MySQL操作類

前面我們示範了一個簡單的資料庫連接配接池,我們再結合之前的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();
           
    }
}