posts - 23,comments - 12,trackbacks - 0
          原文鏈接:http://www.javaresearch.org/article/showarticle.jsp?column=106&thread=8512

          author: evan

          email: evan_zhao@hotmail.com
              
          背景
          1.    需要將數據庫查詢結果在JSP中以列表方式顯示
          2.    在一個良好的J2EE模式中數據庫查詢一般用DAO實現(Data Access Object), JSP僅用于顯示數據

          問題
              通過JDBC ResultSet可獲取查詢結果(存在于數據庫緩沖區內),但在Statement、Connection關閉后ResultSet即不可用。因此需要一種方式取出所有查詢結果并傳遞至JSP頁面。

          解決方法一
              使用Value Object。將每條記錄均封裝成JavaBean對象,把這些對象裝入Collection傳送給JSP顯示。這種方法的缺點是每一種查詢都需要定義一個java class,并且將記錄數據封裝成java對象時也需要很多額外的代碼。
          示例代碼:

          1. //查詢數據代碼
          2.   Connection conn = DBUtil.getConnection();
          3.   PreparedStatement pst = null;
          4.   ResultSet rs = null;
          5.   try{
          6.     String sql=“select emp_code, real_name from t_employee where organ_id=?”;
          7.     pst = conn.preparedStatement(sql);
          8.     pst.setString(1, “101”);
          9.     ResultSet rs = pst.executeQuery();
          10.     List list = new ArrayList();
          11.     Employee emp;
          12.     while (rs.next()){
          13.       emp = new Employee();
          14.       emp.setReakName(rs.getString(“real_name”));
          15.       emp.setEmpCode(rs.getString(“emp_code”));
          16.       …
          17.       list.add(emp);
          18.     }
          19.     return list;
          20.   }finally{
          21.     DBUtil.close(rs, pst ,conn);
          22.   }
          23. //jsp顯示部分代碼
          24. <%
          25.   List empList = (List)request.getAttribute(“empList”);
          26.   if (empList == null) empList = Collections.EMPTY_LIST;
          27. %>
          28. <table  cellspacing="0" width=”90%”>
          29.     <tr>  <td>代碼</td> <td>姓名</td>  </tr>
          30. <%
          31.   Employee emp;
          32.   for (int i=0; i< empList.size(); i++){
          33.     emp = (Employee) empList.get(i);
          34. %>
          35.     <tr>  
          36.       <td><%= emp.getEmpCode()%></td> 
          37.       <td><%= emp.getRealName()%></td>  
          38.     </tr>
          39. <%
          40.   }// end for
          41. %>
          42. </table>


          解決方法二
              遍歷ResultSet取出所有數據封裝進Collection。
          具體做法:
          1.    生成一個List對象(List list = new ArrayList() )。
          2.    生成一個Map對象(Map map = new HashMap() )。使用Map封裝一行數據,key為各字段名,value為對應的值。(map.put(“USER_NAME”), rs.getString(“USER_NAME”))
          3.    將第2 步生成的Map對象裝入第1步的list對象中(list.add(map) )。
          4.    重復2、3步直到ResultSet遍歷完畢
          在DBUtil. resultSetToList(ResultSet rs)方法中實現了上述過程(所有列名均使用大寫),可參考使用。

          示例代碼

          1. //查詢數據部分代碼:
          2.   …
          3.   Connection conn = DBUtil.getConnection();
          4.   PreparedStatement pst = null;
          5.   ResultSet rs = null;
          6.   try{
          7.     String sql=“select emp_code, real_name from t_employee where organ_id=?”;
          8.     pst = conn.preparedStatement(sql);
          9.     pst.setString(1, “101”);
          10.     rs = pst.executeQuery();
          11.     List list = DBUtil. resultSetToList(ResultSet rs);
          12.     return list;
          13.   }finally{
          14.     DBUtil.close(rs, pst ,conn);
          15.   }
          16. //JSP顯示部分代碼
          17. <%
          18.   List empList = (List)request.getAttribute(“empList”);
          19.   if (empList == null) empList = Collections.EMPTY_LIST;
          20. %>
          21. <table  cellspacing="0" width=”90%”>
          22.     <tr>  <td>代碼</td> <td>姓名</td>  </tr>
          23. <%
          24.   Map colMap;
          25.   for (int i=0; i< empList.size(); i++){
          26.     colMap = (Map) empList.get(i);
          27. %>
          28.   <tr>  
          29.     <td><%=colMap.get(“EMP_CODE”)%></td> 
          30.     <td><%=colMap.get(“REAL_NAME”)%></td>  
          31.   </tr>
          32. <%
          33.   }// end for
          34. %>
          35. </table>


          解決方法三
              使用RowSet。
          RowSet是JDBC2.0中提供的接口,Oracle對該接口有相應實現,其中很有用的是oracle.jdbc.rowset.OracleCachedRowSet。 OracleCachedRowSet實現了ResultSet中的所有方法,但與ResultSet不同的是,OracleCachedRowSet中的數據在Connection關閉后仍然有效。

          oracle的rowset實現在http://otn.oracle.com/software/content.html的jdbc下載里有,名稱是ocrs12.zip

          示例代碼

          1. //查詢數據部分代碼:
          2.   import javax.sql.RowSet;
          3.   import oracle.jdbc.rowset.OracleCachedRowSet;
          4.   …
          5.   Connection conn = DBUtil.getConnection();
          6.   PreparedStatement pst = null;
          7.   ResultSet rs = null;
          8.   try{……
          9.     String sql=“select emp_code, real_name from t_employee where organ_id=?”;
          10.     pst = conn.preparedStatement(sql);
          11.     pst.setString(1, “101”);
          12.     rs = pst.executeQuery();
          13.     OracleCachedRowSet ors = newOracleCachedRowSet();
          14.     //將ResultSet中的數據封裝到RowSet中
          15.     ors.populate(rs);
          16.     return ors;
          17.   }finally{
          18.     DBUtil.close(rs, pst, conn);
          19.   }
          20. //JSP顯示部分代碼
          21. <%
          22.   javax.sql.RowSet empRS = (javax.sql.RowSet) request.getAttribute(“empRS”);
          23. %>
          24. <table  cellspacing="0" width=”90%”>
          25.     <tr>  <td>代碼</td> <td>姓名</td>  </tr>
          26. <%
          27.   if (empRS != nullwhile (empRS.next() ) {
          28. %>
          29.   <tr>  
          30.     <td><%= empRS.get(“EMP_CODE”)%></td> 
          31.     <td><%= empRS.get(“REAL_NAME”)%></td>  
          32.   </tr>
          33. <%
          34.   }// end while
          35. %>
          36. </table>


          適用場合
            方法一使用于定制的查詢操作
            方法二適用于多條查詢語句或需要對查詢結果進行處理的情況。
            方法三適合于單條查詢語句,適用于快速開發。


          相關鏈接
              如果需要分頁顯示請參考:JSP分頁技術實現
              如果查詢結果需要生成WORD或者EXCEL,請參考:使用jsp實現word、excel格式報表打印

          附:DBUtil代碼
          1. import java.util.List;
          2. import java.util.ArrayList;
          3. import java.util.Map;
          4. import java.util.HashMap;
          5. import java.util.Properties;
          6. import java.util.Collections;
          7. import java.sql.Connection;
          8. import java.sql.SQLException;
          9. import java.sql.ResultSet;
          10. import java.sql.ResultSetMetaData;
          11. import java.sql.Statement;
          12. import java.sql.PreparedStatement;
          13. import javax.naming.Context;
          14. import javax.naming.InitialContext;
          15. import javax.naming.NamingException;
          16. import javax.sql.DataSource;
          17. public class DBUtil{
          18.     private static final String JDBC_DATA_SOURCE = "java:comp/env/jdbc/DataSource";
          19.     /**
          20.      enableLocalDebug: 是否在本地調試。<br>
          21.      值為true時如果查找數據源失敗則使用DriverManager與數據庫建立連接;
          22.      如果為false則只查找數據源建立數據庫連接。
          23.      默認為false。<br>
          24.      可通過系統屬性jdbc.enable_local_debug=true設置enableLocalDebug為true,啟用本地調試:<br>
          25.      增加JVM parameter: -Djdbc.enable_local_debug=true
          26.      */
          27.     private static boolean enableLocalDebug = false;
          28.     static{
          29.         enableLocalDebug = Boolean.getBoolean ("jdbc.enable_local_debug");
          30.     }
          31.     private static Context ctx = null;
          32.     private static javax.sql.DataSource ds = null;
          33.     private static void initDataSource() throws Exception{
          34.         // Put connection properties in to a hashtable.
          35.         if (ctx == null) {
          36.             ctx = new InitialContext();
          37.         }
          38.         if (ds == null) {
          39.             ds = (javax.sql.DataSource) ctx.lookup(JDBC_DATA_SOURCE);
          40.         }
          41.     }        
          42.     /**
          43.      * 查找應用服務器數據源,從數據源中獲得數據庫連接。<br><br>
          44.      * 在本地調試時如果查找數據源失敗并且enableLocalDebug==true
          45.      * 則根據系統屬性使用java.sql.DriverManager建立連接。<br>
          46.      * 本地調試時可配置的系統屬性如下:<br>
          47.      * <p>
          48.      *     #jdbc驅動程序名 <br>
          49.      *     jdbc.driver=<i>oracle.jdbc.driver.OracleDriver</i> <br> <br>
          50.      *     #數據庫連接串<br>
          51.      *     jdbc.url=<i>jdbc:oracle:thin:@10.1.1.1:1521:ocrl</i> <br> <br>
          52.      *     #數據庫用戶名<br>
          53.      *     jdbc.username=<i>scott</i> <br> <br>
          54.      *     #數據庫用戶密碼<br>
          55.      *     jdbc.password=<i>tiger</i> <br>
          56.      * </p>
          57.      * 可通過JVM參數設置上述系統屬性:<br>
          58.      * -Djdbc.driver=oracle.jdbc.driver.OracleDriver 
          59.      *  -Djdbc.url=jdbc:oracle:thin:@10.1.1.1:1521:ocrl
          60.      *  -Djdbc.username=scott -Djdbc.password=tiger
          61.      * @return Connection
          62.      * @throws NamingException 如果數據源查找失敗
          63.      * @throws SQLException 如果建立數據庫連接失敗
          64.      */
          65.     public static Connection getConnection() throws  SQLException{
          66.         try{
          67.             initDataSource();
          68.             return ds.getConnection();
          69.         }catch(SQLException sqle){
          70.             throw sqle;
          71.         }catch(Exception ne){
          72.             if (enableLocalDebug){
          73.                 return getTestConn();
          74.             }else{
          75.                 throw new RuntimeException(ne.toString());
          76.             }
          77.         }
          78.     }
          79.     //通過DriverManager建立本地測試連接
          80.     private static Connection getTestConn(){
          81.       try {
          82.           String driver = System.getProperty("jdbc.driver");
          83.           System.out.println("jdbc.driver="+driver);
          84.           String url = System.getProperty("jdbc.url");
          85.           System.out.println("jdbc.url="+url);
          86.           String userName = System.getProperty("jdbc.username");
          87.           System.out.println("jdbc.username="+userName);
          88.           String password = System.getProperty("jdbc.password");
          89.           System.out.println("jdbc.password="+password);
          90.           Class.forName(driver).newInstance();
          91.           return java.sql.DriverManager.getConnection(url, userName, password);
          92.       }
          93.       catch (Exception ex) {
          94.         ex.printStackTrace();
          95.         throw new RuntimeException(ex.getMessage());
          96.       }
          97.     }
          98.     /**
          99.      * 將查詢結果封裝成List。<br>
          100.      * List中元素類型為封裝一行數據的Map,Map key為字段名(大寫),value為相應字段值
          101.      * @param rs ResultSet
          102.      * @return List
          103.      * @throws java.sql.SQLException
          104.      */
          105.     public static List resultSetToList(ResultSet rs) throws java.sql.SQLException{
          106.         if (rs==nullreturn Collections.EMPTY_LIST;
          107.         ResultSetMetaData md = rs.getMetaData();
          108.         int columnCount = md.getColumnCount();
          109.         List list = new ArrayList();
          110.         Map rowData;
          111.         while (rs.next()){
          112.             rowData = new HashMap(columnCount);
          113.             for (int i=1; i<=columnCount; i++){
          114.                 rowData.put(md.getColumnName(i),rs.getObject(i));
          115.             }
          116.             list.add(rowData);
          117.         }
          118.         return list;
          119.     }
          120.     /**
          121.      * 關閉ResultSet、Statement和Connection
          122.      * @param rs ResultSet to be closed
          123.      * @param stmt Statement or PreparedStatement  to be closed
          124.      * @param conn Connection  to be closed
          125.      */
          126.     public static void close(ResultSet rs, Statement stmt, Connection conn){
          127.             if (rs != nulltry{
          128.                 rs.close();
          129.             }catch(java.sql.SQLException ex){
          130.                 ex.printStackTrace();
          131.             }
          132.             if (stmt != nulltry{
          133.                  stmt.close();
          134.             }catch(java.sql.SQLException ex){
          135.                 ex.printStackTrace();
          136.             }
          137.             if (conn != nulltry{
          138.                 conn.close();
          139.             }catch(java.sql.SQLException ex){
          140.                 ex.printStackTrace();
          141.             }
          142.     }
          143. }// end of DBUtil
          posted on 2005-09-26 17:24 my java 閱讀(461) 評論(0)  編輯  收藏 所屬分類: java 轉帖
          主站蜘蛛池模板: 汉阴县| 蕲春县| 驻马店市| 宜丰县| 斗六市| 淮安市| 河源市| 汶川县| 色达县| 石渠县| 雅安市| 新郑市| 徐汇区| 林西县| 彭州市| 石台县| 临汾市| 长宁县| 金山区| 曲靖市| 潞城市| 顺昌县| 宕昌县| 江西省| 游戏| 镇江市| 沐川县| 比如县| 图木舒克市| 南江县| 万山特区| 文安县| 马边| 杭锦旗| 泊头市| 呼图壁县| 教育| 镇雄县| 金坛市| 关岭| 十堰市|