jdbc總結 – JAVA編程語言程序開發技術文章

jdbc
1.    連接數據庫的步驟:
1)       註冊驅動
2)       建立連接
3)       創建語句
4)       執行語句
5)       處理結果
6)       釋放資源(註意關閉的順序)
實例//1.註冊驅動
     
[java]
 DriverManager.registerDriver(newcom.mysql.jdbc.Driver()); 
       
       System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver"); 
       
        Class.forName("com.mysql.jdbc.Driver");//推薦方式 
         
       //2.建立連接 
        
        String url = "jdbc:mysql:localhost:3306/jdbc"; 
        String user = "root"; 
        String password = "mysql"; 
Connection conn = DriverManager.getConnection(url,user,password); 
       
       //3.創建語句 
       Statement st = conn.createStatement(); 
       
       //4.執行語句 
       ResultSet rs = st.executeQuery("select * from user"); 
       //5.處理結果 
       while(rs.next()){//按行來遍歷 
System.out.println(rs.getObject(1) + "\t" + rs.getObject(2) + "\t" +rs.getObject(3) + "\t" + rs.getObject(4)); 
       } 
       //6.釋放資源(註意關閉的順序) 
       rs.close(); 
       st.close(); 
       conn.close(); 

2.    註意在jdbc中的sql註入問題,解決的辦法是使用PreparedStatement :PreparedStatement ps = null;// 利用PreparedStatement而不用Statement是因為PreparedStatement能夠對輸入的內容進行過濾,除去sql的關鍵字,防止此問題。
3.    數據庫中對大文本的寫入和讀取:clob類的處理
[java]
public class ClobTest { 
  
    /**
     * @param args
     * @throws Exception
     */ 
    public static void main(String[] args) throws Exception { 
       //create(); 
        read(); 
    } 
     //數據庫的讀取操作 
    static void read() throws SQLException, Exception { 
       Connection conn = null; 
       Statement st = null; 
       ResultSet rs = null; 
       try { 
           conn = JdbcUtils.getConnection(); 
           // 3.創建語句 
           st = conn.createStatement(); 
           // 4.執行語句 
           rs = st.executeQuery("select big_text from clob_test"); 
           // 5.處理結果 
           while (rs.next()) {// 按行來遍歷 
              Reader reader = rs.getCharacterStream(1); 
              Filefile = newFile("CRUD_bak.java"); 
              Writerwriter = new BufferedWriter(new FileWriter(file)); 
              char[] buff = new char[1024]; 
              for(int i = 0; (i = reader.read(buff))>0;){ 
                  writer.write(buff,0, i); 
              } 
              writer.close(); 
              reader.close(); 
              
           } 
       } finally { 
           JdbcUtils.free(rs, st, conn); 
       } 
    } 
    
    //數據庫的創建操作 
    static void create() throws SQLException, IOException { 
       Connection conn = null; 
       PreparedStatement ps = null; 
       ResultSet rs = null; 
       try { 
           conn = JdbcUtils.getConnection(); 
  
           // 3.創建語句 
           String sql = "insertinto clob_test(big_text) values(?)"; 
           ps = conn.prepareStatement(sql); 
           File file = new File("src/com/lcq/jdbc/CRUD.java"); 
           Reader reader = newBufferedReader(newFileReader(file)); 
           //傳遞大塊的文本文檔 
           ps.setCharacterStream(1,reader, file.length()); 
           int i = ps.executeUpdate(); 
           reader.close(); 
           System.out.println("i = " + i); 
           
       } finally { 
           JdbcUtils.free(rs, ps, conn); 
       } 
    } 

4.    問題blob類型讀取二進制文件
數據庫編譯時異常的處理,編寫自己的異常類
[java]
package com.lcq.jdbc.impl; 
  
public class DaoException extends RuntimeException { 
  
    /**
     *
     */ 
    private static final long serialVersionUID = 1L; 
  
    public DaoException() { 
       // TODO Auto-generatedconstructor stub 
    } 
  
    public DaoException(String message) { 
       super(message); 
       // TODO Auto-generatedconstructor stub 
    } 
  
    public DaoException(Throwablecause) { 
       super(cause); 
       // TODO Auto-generatedconstructor stub 
    } 
  
    public DaoException(String message, Throwable cause) { 
       super(message, cause); 
       // TODO Auto-generatedconstructor stub 
    } 
  

在使用時 
catch(SQLException e){ 
           //異常的處理,轉化為運行時異常 
           throw new DaoException(e.getMessage(),e); 
    } 

在sql中SQLException是編譯時異常,所以要拋出,但是如果隻是向上拋出的話,會導致業務層和數據訪問層的關系復雜,後期維護不便;因此最好的解決方法是在數據訪問層中將異常catch住,編寫異常類進行處理,在運行時如果上層能夠處理就處理。從而使業務層和數據訪問層耦合度減少。
5.    一個類的實例化的過程中首先執行的是靜態代碼塊,然後是構造函數。
6.    
事務的處理問題:
[java]
/**
 * 事務處理范例
 * 從賬戶1轉賬到賬戶2十元
 *
 */ 
static void test() throws SQLException { 
       Connection conn = null; 
       Statement st = null; 
       ResultSet rs = null; 
       Savepoint sp = null; 
       try { 
           conn = JdbcUtils.getConnection(); 
           // 3.創建語句 
           Conn.setAutoCommit(false);//設置自動提交無效 
           st = conn.createStatement(); 
           // 4.執行語句 
           String sql = "updateuser set money=money-10 where id=1"; 
          st.executeUpdate(sql); 
           //設置回滾點 
           sp =conn.setSavepoint(); 
           sql = "update userset money=money+10 where id=3"; 
          st.executeUpdate(sql); 
           sql = "selectmoney from user where id=2"; 
           rs = st.executeQuery(sql); 
           float money = 0.0f; 
           
           // 5.處理結果 
           if (rs.next()) {// 按行來遍歷 
              money = rs.getFloat("money"); 
           } 
           if(money > 300){ 
              throw new RuntimeException("已經達到最大值!"); 
              
           } 
           sql = "update userset money=money+10 where id=2"; 
           st.executeUpdate(sql); 
           conn.commit(); 
             
       } catch(RuntimeException e){ 
           if(conn != null && sp != null) 
              //回滾到設置的點 
              conn.rollback(sp); 
           //遞交,使以上操作有效 
               conn.commit(); 
              throw e; 
       }catch(SQLException e){ 
           if(conn != null) 
              conn.rollback(); 
              throwe; 
       }finally { 
           JdbcUtils.free(rs, st, conn); 
       } 
    } 

7.    跨越多個數據源的事務(JTA)實現分佈式的數據處理,事務處理步驟:
1)       打開事務
2)       提交事務
3)       回滾事務
8.    在數據庫中編寫組件(函數),通過ps = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//能夠得到數據庫中的組件。這樣通過組件可以在用戶向數據庫中添加數據時,在返回時可以用組件對結果進行標識,說明數據已經在數據庫中得到更新。
9.    批處理,對sql語句的打包。
10. 
根據用戶的查詢需求進行查詢,並將結果封裝為Map返回www.aiwalls.com
[java]
public classResultSetMetaDataTest { 
  
    /**
     * @param args
     * @throws SQLException
     */ 
    public static void main(String[] args) throws SQLException { 
       List<Map<String, Object>> datas = read("select * from user"); 
       System.out.println(datas); 
    } 
    static List<Map<String, Object>> read(String sql) throws SQLException { 
       Connection conn = null; 
       PreparedStatement ps = null; 
       ResultSet rs = null; 
       try { 
           conn = JdbcUtils.getConnection(); 
       
           ps = conn.prepareStatement(sql); 
           
           rs = ps.executeQuery(); 
           ResultSetMetaDatarsmd = rs.getMetaData(); 
           //得到結果集的列數 
           intcount = rsmd.getColumnCount(); 
           String[] colNames = new String[count]; 
           for(int i = 1; i < colNames.length;i++){ 
              colNames[i-1] = rsmd.getColumnName(i); 
           } 
           List<Map<String, Object>> datas = newArrayList<Map<String, Object>>(); 
           // 5.處理結果 
           while (rs.next()) {// 按行來遍歷,將每一行添加到map中,list中最後存放的是表 
              Map<String,Object> data = new HashMap<String, Object>(); 
              for(inti = 1;i<= colNames.length;i++){ 
                  data.put(colNames[i-1],rs.getObject(i)); 
              } 
              datas.add(data); 
           } 
           return datas; 
       } finally { 
           JdbcUtils.free(rs, ps, conn); 
       } 
    } 
  

11. 對象與關系的映射(利用反射)
[java]
public class ORMTest { 
  
    /**
     * @param args
     * @throwsInvocationTargetException
     * @throwsIllegalAccessException
     * @throws SQLException
     * @throwsIllegalArgumentException
     * @throws InstantiationException
     */ 
    public static void main(String[] args) throws IllegalArgumentException, 
           SQLException, IllegalAccessException,InvocationTargetException, 
           InstantiationException { 
  
       User user = (User) getObject( 
              "select idas Id ,name as Name, birthday as Birthday,money as Money from user whereid=2", 
              User.class); 
       System.out.println(user); 
    } 
  
    static ObjectgetObject(String sql, Class clazz) throws SQLException, 
           IllegalArgumentException, IllegalAccessException, 
           InvocationTargetException, InstantiationException { 
       Connection conn = null; 
       PreparedStatement ps = null; 
       ResultSet rs = null; 
       try { 
           conn = JdbcUtils.getConnection(); 
  
           ps = conn.prepareStatement(sql); 
  
           rs = ps.executeQuery(); 
           ResultSetMetaData rsmd = rs.getMetaData(); 
           // 得到結果集的列數 
           int count = rsmd.getColumnCount(); 
           String[] colNames = new String[count]; 
           for (int i = 1; i <= colNames.length; i++) { 
              colNames[i – 1] = rsmd.getColumnLabel(i); 
           } 
  
           Object object = null; 
           Method[] ms = clazz.getMethods(); 
  
           // 5.處理結果 
           if (rs.next()) {// 按行來遍歷,將每一行添加到map中,list中最後存放的是表 
               object = clazz.newInstance(); 
              for (int i = 0; i < colNames.length; i++) { 
                  String colName = colNames[i]; 
                  String methodName = "set" + colName; 
                  // System.out.println(methodName); 
                  for (Method m : ms) { 
                     if (methodName.equals(m.getName())) { 
                         m.invoke(object, rs.getObject(colName)); 
                     } 
                  } 
              } 
           } 
           return object; 
       } finally { 
           JdbcUtils.free(rs, ps, conn); 
       } 
    } 

12. 創建數據庫連接池,先創建多個連接,將連接一次放在List的尾部,用的時候從List的頭部取出連接,使用連接;用完釋放連接的時候是將連接返回到連接池的尾部,供後邊的用戶使用。達到連接重復使用的目地。
[java]
/**
 *
 * 創建數據庫連接池
 */ 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.SQLException; 
import java.util.LinkedList; 
  
public class MyDataSource { 
    
    private static String url = "jdbc:mysql://localhost:3306/jdbc"; 
    private static String user = "root"; 
    private static String password = "mysql"; 
    
    
    private LinkedList<Connection>connectionsPoll = new LinkedList<Connection>(); 
    public MyDataSource(){ 
       for(int i = 0; i<5;i++){ 
           try { 
              this.connectionsPoll.addLast(this.createConnection()); 
           } catch (SQLException e) { 
               throw newExceptionInInitializerError(e); 
           } 
       } 
    } 
    public Connection getConnection(){ 
       return this.connectionsPoll.removeFirst(); 
    } 
    private Connection createConnection() throws SQLException{ 
       return DriverManager.getConnection(url, user, password); 
    } 
    public void free(Connection conn){ 
       this.connectionsPoll.addLast(conn); 
    } 
  

13. 對創建連接的優化,利用dbcp作為數據源,從數據源中取出連接。編寫自己的數據源。對代碼的優化是從“變與不變”入手的。
14. 通過模板模式對增刪改查進行優化,利用抽象和繼承實現。
15. 利用工廠模式和sping對數據庫的封裝進行最終版本的實現。

摘自 liuchangqing123

發佈留言