自定義一個jdbc框架

一、數據庫連接池: 

  在一般用JDBC 進行連接數據庫進行CRUD操作時,每一次都會:

    通過:java.sql.Connection conn = DriverManager.getConnection(url,user,password); 重新獲取一個數據庫的鏈接再進行操作,這樣用戶每次請求都需要向數據庫獲得鏈接,而數據庫創建連接通常需要消耗相對較大的資源,創建時間也較長。


      
        所以爲了減少服務器的壓力,便可用連接池的方法:在啓動Web應用時,數據就創建好一定數量的Connection鏈接
  存放到一個容器中,然後當用戶請求時,服務器則向容器中獲取Connection鏈接來處理用戶的請求,當用戶的請求完成後,
  又將該Connection 鏈接放回到該容器中。這樣的一個容器稱爲連接池。

    
  
  編寫一個基本的連接池實現連接複用
       步驟:
       1、建立一個數據庫連接池容器。(因爲方便存取,則使用LinkedList集合)
       2、初始化一定數量的連接,放入到容器中。
       3、等待用戶獲取連接對象。(該部分要加鎖)
          |---記得刪除容器中對應的對象,放置別人同時獲取到同一個對象。
       4、提供一個方法,回收用戶用完的連接對象。
       5、要遵循先入先出的原則。

複製代碼
 1 import java.io.InputStream;
 2 import java.sql.Connection;
 3 import java.sql.DriverManager;
 4 import java.sql.SQLException;
 5 import java.util.LinkedList;
 6 import java.util.Properties;
 7 
 8 
 9 /**
10  * 一個基本的數據連接池:  
11  * 1、初始化時就建立一個容器,來存儲一定數量的Connection 對象
12  * 2、用戶通過調用MyDataSource 的getConnection 來獲取Connection 對象。
13  * 3、再通過release 方法來回收Connection 對象,而不是直接關閉連接。
14  * 4、遵守先進先出的原則。
15  *  
16  *     
17  * @author 賀佐安
18  *
19  */
20 public class MyDataSource {
21     private static String url = null;
22     private static String password = null;
23     private static String user = null ;
24     private static String DriverClass = null;
25     private static LinkedList<Connection> pool = new LinkedList<Connection>() ;
26 //    註冊數據庫驅動
27     static {
28         try {
29             InputStream in = MyDataSource.class.getClassLoader()
30                     .getResourceAsStream("db.properties");
31             Properties prop = new Properties(); 
32             prop.load(in);
33             user = prop.getProperty("user"); 
34             url = prop.getProperty("url") ;
35             password = prop.getProperty("password") ; 
36             DriverClass = prop.getProperty("DriverClass") ;  
37             Class.forName(DriverClass) ;  
38             
39         } catch (Exception e) {
40             throw new RuntimeException(e) ;
41         }  
42     }
43     //初始化建立數據連接池
44     public MyDataSource ()  {
45         for(int i = 0 ; i < 10 ; i ++) {
46             try {
47                 Connection conn = DriverManager.getConnection(url, user, password) ;
48                 pool.add(conn) ;
49             } catch (SQLException e) {
50                 e.printStackTrace();
51             }
52         }
53     }
54     //、從連接池獲取連接
55     public Connection getConnection() throws SQLException {
56         return pool.remove() ;
57     } 
58     // 回收連接對象。
59     public void release(Connection conn) {
60         System.out.println(conn+"被回收");
61         pool.addLast(conn) ;
62     } 
63     public int getLength() {
64         return pool.size() ;
65     }
66 }
複製代碼

  這樣當我們要使用Connection 連接數據庫時,則可以直接使用連接池中Connection 的對象。測試如下:

複製代碼
 1 import java.sql.Connection;
 2 import java.sql.SQLException;
 3 
 4 import org.junit.Test;
 5 
 6 
 7 public class MyDataSourceTest {
 8     
 9     
10     /**
11      * 獲取數據庫連接池中的所有連接。
12      */
13     @Test
14     public void Test() {
15         MyDataSource mds = new MyDataSource() ; 
16         Connection conn = null ;
17         try {
18             
19             for (int i = 0 ; i < 20 ; i ++) {
20                 conn = mds.getConnection() ;
21                 System.out.println(conn+"被獲取;連接池還有:"+mds.getLength()); 
22                 mds.release(conn) ;
23             } 
24         } catch (SQLException e) {
25             e.printStackTrace();
26         } 
27     }
28 }
複製代碼

  再運行的時候,可以發現,循環10次後,又再一次獲取到了第一次循環的得到的Connection對象。所以,這樣可以大大的減輕數據庫的壓力。上面只是一個簡單的數據庫連接池,不完美的便是,回收需要調用數據池的release() 方法來進行回收,那麼可以不可以直接調用Connection 實例的close 便完成Connection 對象的回收呢?

 


二、數據源:  

    > 編寫連接池需實現javax.sql.DataSource接口。
      > 實現DataSource接口,並實現連接池功能的步驟:
        1、在DataSource構造函數中批量創建與數據庫的連接,並把創建的連接加入LinkedList對象中。

      2、實現getConnection方法,讓getConnection方法每次調用時,從LinkedList中取一個Connection返回給用戶。當用戶使用完Connection,調用Connection.close()方法時,Collection對象應保證將自己返回到LinkedList中,而不要把conn還給數據庫。

    利用動態代理和包裝設計模式來標準的數據源。

    1、包裝設計模式實現標準數據源:

      這裏的用包裝設計模式,便是將Connection 接口進行包裝。簡單總結一下包裝設計模式的步驟:

          a)定義一個類,實現與被包裝類()相同的接口。
                |----可以先自己寫一個適配器,然後後面繼承這個適配器,改寫需要改寫的方法,提高編程效率。
             b)定義一個實例變量,記住被包裝類的對象的引用。
             c)定義構造方法,轉入被包裝類的對象。

           e)對需要改寫的方法,改寫。
                    f)對不需要改寫的方法,調用原來被包裝類的對應方法。

      所以先編寫一個類似適配器的類,將Connection 接口的方法都進行實現:

 View Code

      然後再對Connection 接口進行包裝,將close 方法修改掉:

複製代碼
 1 import java.sql.Connection;
 2 import java.sql.SQLException;
 3 import java.util.LinkedList;
 4 /**
 5  * 對MyConnectionAdapter 進行包裝處理 
 6  * @author 賀佐安
 7  *
 8  */
 9 public class MyConnectionWrap extends MyConnectionAdapter {
10 
11     private LinkedList<Connection> pool = new LinkedList<Connection>() ;
12     public MyConnectionWrap(Connection conn ,LinkedList<Connection> pool ) {
13         super(conn); 
14         this.pool = pool ; 
15     }
16     
17     //改寫要實現的方法
18     public void close() throws SQLException {
19         pool.addLast(conn) ;
20     }
21 }
複製代碼

      編寫標準數據源:

複製代碼
  1 import java.io.PrintWriter;
  2 import java.sql.Connection;
  3 import java.sql.DriverManager;
  4 import java.sql.SQLException;
  5 import java.util.LinkedList;
  6 import java.util.ResourceBundle;
  7 
  8 import javax.sql.DataSource;
  9 
 10 
 11 /** 
 12  * 編寫標準的數據源:
 13  * 1、實現DataSource 接口
 14  * 2、獲取在實現類的構造方法中批量獲取Connection 對象,並將這些Connection 存儲
 15  * 在LinkedList 容器中。
 16  * 3、實現getConnection() 方法,調用時返回LinkedList容器的Connection對象給用戶。
 17  * @author 賀佐安
 18  *
 19  */
 20 public class MyDataSource implements DataSource{
 21     private static String url = null;
 22     private static String password = null;
 23     private static String user = null ;
 24     private static String DriverClass = null;
 25     private static LinkedList<Connection> pool = new LinkedList<Connection>() ;
 26 
 27     //    註冊數據庫驅動
 28     static {
 29         try {  
 30             ResourceBundle rb = ResourceBundle.getBundle("db") ;
 31             url = rb.getString("url") ; 
 32             password = rb.getString("password") ; 
 33             user = rb.getString("user") ; 
 34             DriverClass = rb.getString("DriverClass") ;
 35             Class.forName(DriverClass) ;  
 36             
 37             //初始化建立數據連接池
 38             for(int i = 0 ; i < 10 ; i ++) {
 39                 Connection conn = DriverManager.getConnection(url, user, password) ;
 40                 pool.add(conn) ;
 41             }
 42         } catch (Exception e) {
 43             throw new RuntimeException(e) ;
 44         } 
 45         
 46     }
 47     public MyDataSource ()  {  
 48     }
 49     
 50     //、從連接池獲取連接:通過包裝模式
 51     public synchronized Connection getConnection() throws SQLException {
 52         if (pool.size() > 0) {
 53             MyConnectionWrap mcw = new MyConnectionWrap(pool.remove(), pool) ;
 54             return mcw ;
 55         }else {
 56             throw new RuntimeException("服務器繁忙!"); 
 57         }
 58     }
 59     
 60     // 回收連接對象。
 61     public void release(Connection conn) {
 62         System.out.println(conn+"被回收");
 63         pool.addLast(conn) ;
 64     }
 65     
 66     public int getLength() {
 67         return pool.size() ;
 68     }
 69     
 70     
 71     @Override
 72     public PrintWriter getLogWriter() throws SQLException {
 73         return null;
 74     }
 75     @Override
 76     public void setLogWriter(PrintWriter out) throws SQLException {
 77         
 78     }
 79     @Override
 80     public void setLoginTimeout(int seconds) throws SQLException {
 81         
 82     }
 83     @Override
 84     public int getLoginTimeout() throws SQLException {
 85         return 0;
 86     }
 87     @Override
 88     public <T> T unwrap(Class<T> iface) throws SQLException {
 89         return null;
 90     }
 91     @Override
 92     public boolean isWrapperFor(Class<?> iface) throws SQLException {
 93         return false;
 94     }
 95     @Override
 96     public Connection getConnection(String username, String password)
 97             throws SQLException {
 98         return null;
 99     }
100     
101 }
複製代碼

 

 

  2、動態代理實現標準數據源:

    相對於用包裝設計來完成標準數據源,用動態代理則方便許多:

  

複製代碼
  1 import java.io.PrintWriter;
  2 import java.lang.reflect.InvocationHandler;
  3 import java.lang.reflect.Method;
  4 import java.lang.reflect.Proxy;
  5 import java.sql.Connection;
  6 import java.sql.DriverManager;
  7 import java.sql.SQLException;
  8 import java.util.LinkedList;
  9 import java.util.ResourceBundle;
 10 
 11 import javax.sql.DataSource;
 12 
 13 
 14 /** 
 15  * 編寫標準的數據源:
 16  * 1、實現DataSource 接口
 17  * 2、獲取在實現類的構造方法中批量獲取Connection 對象,並將這些Connection 存儲
 18  * 在LinkedList 容器中。
 19  * 3、實現getConnection() 方法,調用時返回LinkedList容器的Connection對象給用戶。
 20  * @author 賀佐安
 21  *
 22  */
 23 public class MyDataSource implements DataSource{
 24     private static String url = null;
 25     private static String password = null;
 26     private static String user = null ;
 27     private static String DriverClass = null;
 28     private static LinkedList<Connection> pool = new LinkedList<Connection>() ;
 29 
 30     //    註冊數據庫驅動
 31     static {
 32         try {  
 33             ResourceBundle rb = ResourceBundle.getBundle("db") ;
 34             url = rb.getString("url") ; 
 35             password = rb.getString("password") ; 
 36             user = rb.getString("user") ; 
 37             DriverClass = rb.getString("DriverClass") ;
 38             Class.forName(DriverClass) ;  
 39             
 40             //初始化建立數據連接池
 41             for(int i = 0 ; i < 10 ; i ++) {
 42                 Connection conn = DriverManager.getConnection(url, user, password) ;
 43                 pool.add(conn) ;
 44             }
 45         } catch (Exception e) {
 46             throw new RuntimeException(e) ;
 47         }  
 48     }
 49     public MyDataSource ()  { 
 50         
 51     }
 52     
 53     //、從連接池獲取連接:通過動態代理
 54     public Connection getConnection() throws SQLException {
 55         if (pool.size() > 0) {
 56             final Connection conn  = pool.remove() ; 
 57             Connection proxyCon = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), 
 58                     new InvocationHandler() {
 59                         //策略設計模式:
 60                         @Override
 61                         public Object invoke(Object proxy, Method method, Object[] args)
 62                                 throws Throwable {
 63                             if("close".equals(method.getName())){
 64                                 //誰調用,
 65                                 return pool.add(conn);//當調用close方法時,攔截了,把鏈接放回池中了
 66                             }else{
 67                                 return method.invoke(conn, args);
 68                             } 
 69                         }
 70                     });
 71           return proxyCon ;
 72         }else {
 73             throw new RuntimeException("服務器繁忙!"); 
 74         }
 75     } 
 76     
 77     public int getLength() {
 78         return pool.size() ;
 79     }
 80     
 81     
 82     @Override
 83     public PrintWriter getLogWriter() throws SQLException {
 84         return null;
 85     }
 86     @Override
 87     public void setLogWriter(PrintWriter out) throws SQLException {
 88         
 89     }
 90     @Override
 91     public void setLoginTimeout(int seconds) throws SQLException {
 92         
 93     }
 94     @Override
 95     public int getLoginTimeout() throws SQLException {
 96         return 0;
 97     }
 98     @Override
 99     public <T> T unwrap(Class<T> iface) throws SQLException {
100         return null;
101     }
102     @Override
103     public boolean isWrapperFor(Class<?> iface) throws SQLException {
104         return false;
105     }
106     @Override
107     public Connection getConnection(String username, String password)
108             throws SQLException {
109         return null;
110     } 
111 }
複製代碼

    當然覺得麻煩的則可以直接使用一些開源的數據源如:DBCP、C3P0等。DBCP的原理是用包裝設計模式開發的數據源,而C3P0則是動態代理的。

    1、DBCP的使用:

複製代碼
 1 import java.io.InputStream;
 2 import java.sql.Connection;
 3 import java.sql.SQLException;
 4 import java.util.Properties;
 5 
 6 import javax.sql.DataSource;
 7 
 8 import org.apache.commons.dbcp.BasicDataSourceFactory;
 9 
10 /**
11  * 創建DBCP 工具類
12  * @author 賀佐安
13  *
14  */
15 public class DbcpUtil {
16     private static DataSource ds = null ;
17     static {
18         try {
19             //讀取配置文件
20             InputStream in = DbcpUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties") ;
21             Properties prop = new Properties() ; 
22             prop.load(in) ;
23             
24             //通過BasicDataSourceFactory 的creatDataSurce 方法創建 BasicDataSource 對象。
25             ds = BasicDataSourceFactory.createDataSource(prop) ;
26             
27         } catch (Exception e) {
28             e.printStackTrace();
29         } 
30     }
31     public static DataSource getDs() {
32         return ds ; 
33     }
34     public static Connection getConnection () {
35         try { 
36             return ds.getConnection() ;
37         } catch (SQLException e) {
38             throw new RuntimeException() ;
39         } 
40     }
41 }
複製代碼

    2、C3P0 的使用:

複製代碼
 1 import java.sql.Connection;
 2 import java.sql.SQLException;
 3 
 4 import com.mchange.v2.c3p0.ComboPooledDataSource;
 5 /**
 6  * C3P0 開源數據源的使用
 7  * @author 賀佐安
 8  *
 9  */
10 public class C3p0Util {
11     private static ComboPooledDataSource cpds  = null ;
12     static {
13         
14         cpds = new ComboPooledDataSource() ; 
15     }
16     public static Connection getConnection() {
17         try {
18             return cpds.getConnection() ;
19         } catch (SQLException e) {
20             throw new RuntimeException() ;
21         }
22     }
23 }
複製代碼

  使用這兩個數據源時,直接調用獲取到的Connection 連接的close 方法,也是將連接放到pool中去。

    

 

三、元數據(DatabaseMetaData)信息的獲取

  > 元數據:數據庫、表、列的定義信息。    

  > 元數據信息的獲取:爲了編寫JDBC框架使用。   

      1、數據庫本身信息的獲取:java.sql.DataBaseMateData java.sql.Connection.getMetaData() ;    

      DataBaseMateData 實現類的常用方法:    

        getURL():返回一個String類對象,代表數據庫的URL。     

        getUserName():返回連接當前數據庫管理系統的用戶名。     

        getDatabaseProductName():返回數據庫的產品名稱。    

        getDatabaseProductVersion():返回數據庫的版本號。     

        getDriverName():返回驅動驅動程序的名稱。     

        getDriverVersion():返回驅動程序的版本號。    

        isReadOnly():返回一個boolean值,指示數據庫是否只允許讀操作。   

      2、ParameterMetaData: 代表PerparedStatment 中的SQL 參數元數據信息:    java.sql.ParameterMetaData java.sql.PerparedStatement.getParameterMetaData() ;          

      ParameterMetaData 實現類常用方法:     

        getParameterCount() :獲得指定參數的個數    

        getParameterType(int param) :獲得指定參數的sql類型(驅動可能不支持)

       3、ResultSetMetaData : 代表結果集的源數據信息:相當於SQL 中的 :DESC    java.sql.ResultSetMetaData java.sql.ResultSet.getMetaData() ;                

      java.sql.ResultSetMetaData 接口中常用的方法:     

        a) getColumnCount() : 獲取查詢方法有幾列。     

        b) getColumnName(int index) : 獲取列名:index從1開始。     

        c) getColumnType(int index) : 獲取列的數據類型。返回的是TYPES  中的常量值。

 

 

四、編寫自己的JDBC框架:

    JDBC框架的基本組成:  

    1、核心類:

      a、定義一個指定javax.sql.DataSource 實例的引用變量,通過構造函數獲取指定的實例並給定義的變量。
        b、編寫SQL運行框架。

         DML 語句的編寫:
             1、通過獲取的javax.sql.DataSource 實例,獲取Connection 對象。
             2、通過ParamenterMeteData 獲取數據庫元數據。
   
           DQL 語句的編寫:
             1、通過獲取的DataSource 實例,獲取Connection 對象。
             2、通過ParamenterMeteData、ResultSetMetaData 等獲取數據庫元數據。
             3、用抽象策略設計模式:設計一個ResultSetHandler 接口,作用:將查找出的數據封裝到指定的JavaBean中。 
                    |————這裏的JavaBean,由用戶來指定。
                    抽象策略模式,用戶可以更具具體的功能來擴展成具體策略設計模式。如:查找的一條信息、查找的所有信息。

複製代碼
  1 import java.sql.Connection;
  2 import java.sql.ParameterMetaData;
  3 import java.sql.PreparedStatement;
  4 import java.sql.ResultSet;
  5 import java.sql.SQLException;
  6 import java.sql.Statement;
  7 
  8 import javax.sql.DataSource;
  9 
 10 /**
 11  * 實現JDBC 框架的核心類。
 12  * 在該類中定義了SQL語句完成的方法;
 13  * @author 賀佐安
 14  *
 15  */
 16 public class  MyJdbcFrame {
 17     /**
 18      * javax.sql.DataSource 實例的引用變量
 19      */
 20     private DataSource ds = null ;
 21     /**
 22      * 將用戶指定的DataSource 指定給系統定義的DataSource 實例的引用變量
 23      * @param ds
 24      */
 25     public MyJdbcFrame(DataSource ds ) {
 26         this.ds = ds ; 
 27     }
 28     /**
 29      * 執行UPDATE、DELETE、INSERT 語句。
 30      * @param sql 
 31      * @param obj
 32      */
 33     public void update(String sql , Object[] obj) {
 34         Connection conn = null ; 
 35         PreparedStatement stmt = null ; 
 36         try {
 37             //獲取Connection 對象
 38             conn = ds.getConnection() ;
 39             stmt = conn.prepareStatement(sql) ; 
 40             
 41             // 獲取ParameterMetaData 元數據對象。
 42             ParameterMetaData pmd = stmt.getParameterMetaData() ;
 43             
 44             //獲取SQL語句中需要設置的參數的個數
 45             int parameterCount = pmd.getParameterCount() ;
 46             if (parameterCount > 0) { 
 47                 if (obj == null || obj.length != parameterCount) {
 48                     throw new MyJdbcFrameException( "parameterCount is error!") ;
 49                 } 
 50                 //設置參數:
 51                 for ( int i = 0 ; i < obj.length ; i++) {
 52                     stmt.setObject(i+1, obj[i]) ;
 53                 }
 54             } 
 55             //執行語句:
 56             stmt.executeUpdate() ; 
 57             
 58         } catch(Exception e ) {
 59             throw new MyJdbcFrameException(e.getMessage()) ;
 60         } finally {
 61             release(stmt, null, conn) ;
 62         }
 63     }
 64     
 65     public Object query(String sql , Object[] obj , ResultSetHandler rsh) {
 66         Connection conn = null ; 
 67         PreparedStatement stmt = null ; 
 68         ResultSet rs = null ;
 69         try {
 70             //獲取Connection 對象
 71             conn = ds.getConnection() ;
 72             stmt = conn.prepareStatement(sql) ; 
 73             
 74             // 獲取ParameterMetaData 元數據對象。
 75             ParameterMetaData pmd = stmt.getParameterMetaData() ;
 76             
 77             //獲取SQL語句中需要設置的參數的個數
 78             int parameterCount = pmd.getParameterCount() ;
 79             
 80             if (obj.length != parameterCount) {
 81                 throw new MyJdbcFrameException( "'" +sql +"' : parameterCount is error!") ;
 82             } 
 83             //設置參數:
 84             for ( int i = 0 ; i < obj.length ; i++) {
 85                 stmt.setObject(i+1, obj[i]) ;
 86             }
 87             //執行語句:
 88             rs = stmt.executeQuery(); 
 89             
 90             return rsh.handler(rs);
 91         } catch(Exception e ) {
 92             throw new MyJdbcFrameException(e.getMessage()) ;
 93         } finally {
 94             release(stmt, null, conn) ;
 95         } 
 96     } 
 97     /**
 98      * 釋放資源
 99      * @param stmt
100      * @param rs
101      * @param conn
102      */
103     public static void release(Statement stmt 
104                              , ResultSet rs 
105                              , Connection conn) {
106         if(rs != null) {
107             try {
108                 rs.close() ;
109             } catch (SQLException e) {
110                 e.printStackTrace();
111             }
112             rs = null ;
113         }
114         if (stmt != null) { 
115             try {
116                 stmt.close();
117             } catch (SQLException e) {
118                 e.printStackTrace();
119             } 
120             stmt = null ;
121         }
122         if (conn != null) {
123             try {
124                 conn.close();
125             } catch (SQLException e) {
126                 e.printStackTrace();
127             }
128             conn = null ;
129         }
130     } 
131     
132 }
複製代碼

    2、接口:策略模式的接口:ResultSetHandler 。

1 import java.sql.ResultSet;
2 
3 //抽象策略模式
4 public interface ResultSetHandler {
5     public Object handler(ResultSet rs) ;
6 }

    這裏對ResultSetHandler 接口實現一個BeanHandler 實例 :

複製代碼
 1 import java.lang.reflect.Field;
 2 import java.sql.ResultSet;
 3 import java.sql.ResultSetMetaData;
 4 
 5 /**
 6  * 該類獲取ResultSet 結果集中的第一個值,封裝到JavaBean中
 7  * @author 賀佐安
 8  *
 9  */
10 public class BeanHandler implements ResultSetHandler { 
11     //獲取要封裝的JavaBean的字節碼
12     private Class clazz ;
13     public BeanHandler (Class clazz) {
14         this.clazz = clazz ;
15     }
16 
17     public Object handler(ResultSet rs) {
18         try {
19             if (rs.next()) {
20                 //1、獲取結果集的元數據。
21                 ResultSetMetaData rsm = rs.getMetaData() ;
22                 //2、創建JavaBean的實例:
23                 Object obj = clazz.newInstance() ;
24                 //3、將數據封裝到JavaBean中。  
25                 for (int i = 0 ; i < rsm.getColumnCount() ; i ++) {
26                     //獲取屬性名
27                     String columnName = rsm.getColumnName(i+1) ; 
28                     //獲取屬性值
29                     Object value = rs.getObject(i+1) ; 
30                     
31                     Field objField = obj.getClass().getDeclaredField(columnName) ;
32                     objField.setAccessible(true) ;
33                     objField.set(obj, value) ;
34                 }
35                 return obj ;
36             } else {
37                 return null ;
38             }
39         } catch (Exception e) {
40             throw new RuntimeException(e) ;
41         }   
42     } 
43 }
複製代碼

    3、自定義異常類:繼承RuntimeException。如:

複製代碼
1 public class MyJdbcFrameException extends RuntimeException {
2     public MyJdbcFrameException() {
3         super() ; 
4     }
5     public MyJdbcFrameException(String e) {
6         super(e) ;
7     }
8 }
複製代碼

    

  然後就可以將其打包發佈,在以後寫數據庫操作時就可以用自己的JDBC框架了,如果要完成查詢多條語句什麼的,則要實現ResultSetHandler 接口。來完成更多的功能。

  當然,使用DBUtils 則更簡單:Apache 組織提供的一個開源JDBC 工具類庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章