1. 程式人生 > >手把手教你如何自定義DAO框架(重量級乾貨)(yet)

手把手教你如何自定義DAO框架(重量級乾貨)(yet)

https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247484864&idx=2&sn=9721e840eab2b929e9523d82c45a1bb6&chksm=ebd63aecdca1b3fa998f27a185630f7e6b40564cf7cacec8e32818184fcf1d2e23d33757beee&mpshare=1&scene=1&srcid=0206Vt8xydSjEPcErB4rA2az&key=7a4fd26cfac6ce0520c3b75a31a96df31d4be437a8f3317af06cfc9c97b79ac5fbf1bdc6bd5d03aed3ab70644e57d1140efc6bdc63ad85edd4508daea3e8e113732c605adb68dc975c22022d8f989caf&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=EVZTeGFk8lco7QnbdQu1aVcnN2PUGDc58FC5tG6YJ74SpwFYT%2BA%2BC4MKrc8qeCV1

描述:本篇部落格,主要是對於目前實際web專案開發中,對於資料庫操作的一些基本方法的封裝,通過這樣的方式,可以使得開發更加簡單,減少程式碼量,也便於維護和閱讀。其中,主要是講解了三種不同情況的封裝方法,都是自身實際開發過程中,進行積累的,當然,還有很多不足之處,但是基本夠專案的基本開發。

一:非框架的DAO層封裝

其中包含的知識點:

1:連線池

2:資料來源

3:反射

4:資料庫元資料物件

5:基本的jdbc知識

封裝步驟:

(1)匯入dbcp資料來源包

(2)編寫properties檔案,並且命令為dbcpconfig.properties

#連線設定  
   driverClassName=com.mysql.jdbc.Driver  
   url=jdbc:mysql://localhost:3306/填寫要使用的資料庫  
   username=填寫自己的mysql賬號  
   password=填寫自己的mysql密碼  
     
   #<!-- 初始化連線 -->
 
   initialSize=10  
     
   #最大連線數量  
   maxActive=50  
     
   #<!-- 最大空閒連線 --> 
   maxIdle=20  
     
   #<!-- 最小空閒連線 --> 
   minIdle=5  
     
   #<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等於60秒 --> 
   maxWait=60000  
     
     
   #JDBC驅動建立連線時附帶的連線屬性屬性的格式必須為這樣:[屬性名=property;]  
   #注意:"user" 與 "password" 兩個屬性會被明確地傳遞,因此這裡不需要包含他們。  
   connectionProperties=useUnicode=true;characterEncoding=gbk  
     
   #指定由連線池所建立的連線的自動提交(auto-commit)狀態。  
   defaultAutoCommit=true  
     
   #driver default 指定由連線池所建立的連線的只讀(read-only)狀態。  
   #如果沒有設定該值,則“setReadOnly”方法將不被呼叫。(某些驅動並不支援只讀模式,如:Informix)  
   defaultReadOnly=false  
     
   #driver default 指定由連線池所建立的連線的事務級別(TransactionIsolation)。  
   #可用值為下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE  
   defaultTransactionIsolation=READ_UNCOMMITTED

(3)編寫DBCP工具類

publicclassDBCPUtils{  
   privatestaticDataSource ds ;    
   static{  
       //將配置檔案載入進來  
       InputStreamin= DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties") ;  
       Properties props =newProperties() ;  
       try{  
           props.load(in) ;  
           ds = BasicDataSourceFactory.createDataSource(props) ;  
       }catch(Exception e) {  
           thrownewRuntimeException("伺服器忙") ;  
       }  
   }  
     
   //提供獲取連線的方法  
   publicstaticConnectiongetConnection(){  
       try{  
           returnds.getConnection() ;  
       }catch(SQLException e) {  
           thrownewRuntimeException("伺服器忙") ;  
       }  
   }  
}

(4)編寫基本DAO層方法封裝

//自定義框架  
publicclassBaseDao{  
 
   // 執行添改刪語句  
   publicbooleanupdate(String sql, Object...params){  
       // 拿到連線物件  
       Connection conn = DBCPUtils.getConnection();  
       intt =0;  
       try{  
           // 建立預處理命令物件  
           PreparedStatement pstmt = conn.prepareStatement(sql);  
           // 對?進行賦值  
           // 獲取ParameterMetaData物件  
           ParameterMetaData pmd = pstmt.getParameterMetaData();  
           // 拿到?的個數  
           intn = pmd.getParameterCount();  
           if(n >0) {  
               // sql語句裡有?號  
               if(params==null||params.length != n) {  
                   thrownewRuntimeException("引數的個數不匹配");  
               }  
               // 依次給每個?賦值  
               for(inti =0; i < n; i++) {  
                   pstmt.setObject(i +1,params[i]);  
               }  
           }  
 
           t = pstmt.executeUpdate();  
       }catch(SQLException e) {  
           e.printStackTrace();  
       }finally{  
           try{  
               conn.close();// 還回池中了  
           }catch(SQLException e) {  
               // TODO Auto-generated catch block  
               e.printStackTrace();  
           }  
       }  
       returnt >0?true:false;  
   }  
 
   // 執行查詢(返回的結果可能是一個或者多個,或者為null,這個就具體根據返回結果再進行處理即可)  
   publicObjectqueryOne(String sql,Class clazz, Object...params){  
       // 拿到連線物件  
       Connection conn = DBCPUtils.getConnection();  
       try{  
           // 建立預處理命令物件  
           PreparedStatement pstmt = conn.prepareStatement(sql);  
           // 對?進行賦值  
           // 獲取ParameterMetaData物件  
           ParameterMetaData pmd = pstmt.getParameterMetaData();  
           // 拿到?的個數  
           intn = pmd.getParameterCount();  
           if(n >0) {  
               // sql語句裡有?號  
               if(params==null||params.length != n) {  
                   thrownewRuntimeException("引數的個數不匹配");  
               }  
               // 依次給每個?賦值  
               for(inti =0; i < n; i++) {  
                   pstmt.setObject(i +1,params[i]);  
               }  
           }  
 
           ResultSet rs = pstmt.executeQuery();  
           //返回的結果可能是一個或者多個,或者為null  
           returnnewResultSetListenerHandlerImpl().handler(rs, clazz) ;  
       }catch(SQLException e) {  
           thrownewRuntimeException() ;  
       }finally{  
           try{  
               conn.close();// 還回池中了  
           }catch(SQLException e) {  
               // TODO Auto-generated catch block  
               e.printStackTrace();  
           }  
       }  
   }  
 
}

(5)查詢返回結果集與實體bean的封裝物件ResultSetListenerHandlerImpl

//只適用於結果集有多條記錄的情況  
//物件的屬性名和表中的欄位名應當一致  
publicclassResultSetListenerHandlerImpl{  
   publicObject handler(ResultSet rs,Classclazz){        
       List<Object>list=newArrayList<Object>() ;  
       //拿到結果集的元資料物件  
       try{  
           while(rs.next()){  
               ResultSetMetaData rsmd = rs.getMetaData() ;  
               //拿到公有多少列  
               int columnCount = rsmd.getColumnCount() ;  
               //先建立物件  
               Object obj = clazz.newInstance() ;  
               for(int i =0; i < columnCount; i++) {  
                   //拿到列名  
                   String columnName = rsmd.getColumnName(i+1) ;        
                   //拿到物件對應的屬性  
                   Field field = clazz.getDeclaredField(columnName) ;  
                   //設定私有屬性可以訪問  
                   field.setAccessible(true) ;  
                   //拿到此列對應的值  
                   Object objectValue = rs.getObject(i+1) ;  
                   //給屬性賦值  
                   field.set(obj, objectValue) ;  
               }  
               list.add(obj) ;  
           }  
           returnlist;  
       }catch(Exceptione) {  
           thrownewRuntimeException() ;  
       }  
   }  
 
}

上面這個是返回一個List的情況,如果只想是返回單個物件,那麼很簡單,稍微處理一下就可以用下面這個類來實現:

//只適用於結果集只有一條記錄的情況  
//物件的屬性名和表中的欄位名應當一致  
publicclassResultSetHandlerImpl{  
   publicObjecthandler(ResultSet rs, Class clazz){  
       //拿到結果集的元資料物件  
       try{  
           if(rs.next()){  
               ResultSetMetaData rsmd = rs.getMetaData() ;  
               //拿到公有多少列  
               intcolumnCount = rsmd.getColumnCount() ;  
               //先建立物件  
               Object obj = clazz.newInstance() ;  
               for(inti =0; i < columnCount; i++) {  
                   //拿到列名  
                   String columnName = rsmd.getColumnName(i+1) ;        
                   //拿到物件對應的屬性  
                   Field field = clazz.getDeclaredField(columnName) ;  
                   //設定私有屬性可以訪問  
                   field.setAccessible(true) ;  
                   //拿到此列對應的值  
                   Object objectValue = rs.getObject(i+1) ;  
                   //給屬性賦值  
                   field.set(obj, objectValue) ;  
               }  
               returnobj ;  
           }else 
               returnnull;  
       }catch(Exception e) {  
           thrownewRuntimeException() ;  
       }  
   }  
 
}

二:Mybatis的DAO層封裝

(1)一般先寫介面:

publicinterfaceDAO{  
   /**  
    * 儲存物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObject save(String str, Object obj) throwsException;  
 
   /**  
    * 修改物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObject update(String str, Object obj) throwsException;  
 
   /**  
    * 刪除物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObject delete(String str, Object obj) throwsException;  
 
   /**  
    * 查詢物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObject findForObject(String str, Object obj) throwsException;  
 
   /**  
    * 查詢物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObject findForList(String str, Object obj) throwsException;  
 
   /**  
    * 查詢物件封裝成Map  
    *  
    *@params  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObject findForMap(String sql, Object obj, String key, String value) throwsException;  
}

(2)再寫實現層:

@Repository("daoSupport")  
publicclassDaoSupportimplementsDAO{  
 
   @Resource(name ="sqlSessionTemplate")  
   privateSqlSessionTemplate sqlSessionTemplate;  
 
   /**  
    * 儲存物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObjectsave(String str, Object obj)throwsException{  
       returnsqlSessionTemplate.insert(str, obj);  
   }  
 
   /**  
    * 批量更新  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObjectbatchSave(String str, List objs)throwsException{  
       returnsqlSessionTemplate.insert(str, objs);  
   }  
 
   /**  
    * 修改物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObjectupdate(String str, Object obj)throwsException{  
       returnsqlSessionTemplate.update(str, obj);  
   }  
 
   /**  
    * 批量更新  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicvoidbatchUpdate(String str, List objs)throwsException{  
       SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();  
       // 批量執行器  
       SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);  
       try{  
           if(objs !=null) {  
               for(inti =0, size = objs.size(); i < size; i++) {  
                   sqlSession.update(str, objs.get(i));  
               }  
               sqlSession.flushStatements();  
               sqlSession.commit();  
               sqlSession.clearCache();  
           }  
       }finally{  
           sqlSession.close();  
       }  
   }  
 
   /**  
    * 批量更新  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObjectbatchDelete(String str, List objs)throwsException{  
       returnsqlSessionTemplate.delete(str, objs);  
   }  
 
   /**  
    * 刪除物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObjectdelete(String str, Object obj)throwsException{  
       returnsqlSessionTemplate.delete(str, obj);  
   }  
 
   /**  
    * 查詢物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObjectfindForObject(String str, Object obj)throwsException{  
       returnsqlSessionTemplate.selectOne(str, obj);  
   }  
 
   /**  
    * 查詢物件  
    *  
    *@paramstr  
    *@paramobj  
    *@return 
    *@throwsException  
    */
 
   publicObjectfindForList(String str, Object obj)throwsException{  
       returnsqlSessionTemplate.selectList(str, obj);  
   }  
 
   publicObjectfindForMap(String str, Object obj, String key, String value)throwsException{  
       returnsqlSessionTemplate.selectMap(str, obj, key);  
   }  
}