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.    需要將數(shù)據(jù)庫(kù)查詢結(jié)果在JSP中以列表方式顯示
          2.    在一個(gè)良好的J2EE模式中數(shù)據(jù)庫(kù)查詢一般用DAO實(shí)現(xiàn)(Data Access Object), JSP僅用于顯示數(shù)據(jù)

          問(wèn)題
              通過(guò)JDBC ResultSet可獲取查詢結(jié)果(存在于數(shù)據(jù)庫(kù)緩沖區(qū)內(nèi)),但在Statement、Connection關(guān)閉后ResultSet即不可用。因此需要一種方式取出所有查詢結(jié)果并傳遞至JSP頁(yè)面。

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

          1. //查詢數(shù)據(jù)代碼
          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取出所有數(shù)據(jù)封裝進(jìn)Collection。
          具體做法:
          1.    生成一個(gè)List對(duì)象(List list = new ArrayList() )。
          2.    生成一個(gè)Map對(duì)象(Map map = new HashMap() )。使用Map封裝一行數(shù)據(jù),key為各字段名,value為對(duì)應(yīng)的值。(map.put(“USER_NAME”), rs.getString(“USER_NAME”))
          3.    將第2 步生成的Map對(duì)象裝入第1步的list對(duì)象中(list.add(map) )。
          4.    重復(fù)2、3步直到ResultSet遍歷完畢
          在DBUtil. resultSetToList(ResultSet rs)方法中實(shí)現(xiàn)了上述過(guò)程(所有列名均使用大寫),可參考使用。

          示例代碼

          1. //查詢數(shù)據(jù)部分代碼:
          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對(duì)該接口有相應(yīng)實(shí)現(xiàn),其中很有用的是oracle.jdbc.rowset.OracleCachedRowSet。 OracleCachedRowSet實(shí)現(xiàn)了ResultSet中的所有方法,但與ResultSet不同的是,OracleCachedRowSet中的數(shù)據(jù)在Connection關(guān)閉后仍然有效。

          oracle的rowset實(shí)現(xiàn)在http://otn.oracle.com/software/content.html的jdbc下載里有,名稱是ocrs12.zip

          示例代碼

          1. //查詢數(shù)據(jù)部分代碼:
          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中的數(shù)據(jù)封裝到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>


          適用場(chǎng)合
            方法一使用于定制的查詢操作
            方法二適用于多條查詢語(yǔ)句或需要對(duì)查詢結(jié)果進(jìn)行處理的情況。
            方法三適合于單條查詢語(yǔ)句,適用于快速開發(fā)。


          相關(guān)鏈接
              如果需要分頁(yè)顯示請(qǐng)參考:JSP分頁(yè)技術(shù)實(shí)現(xiàn)
              如果查詢結(jié)果需要生成WORD或者EXCEL,請(qǐng)參考:使用jsp實(shí)現(xiàn)word、excel格式報(bào)表打印

          附: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: 是否在本地調(diào)試。<br>
          21.      值為true時(shí)如果查找數(shù)據(jù)源失敗則使用DriverManager與數(shù)據(jù)庫(kù)建立連接;
          22.      如果為false則只查找數(shù)據(jù)源建立數(shù)據(jù)庫(kù)連接。
          23.      默認(rèn)為false。<br>
          24.      可通過(guò)系統(tǒng)屬性jdbc.enable_local_debug=true設(shè)置enableLocalDebug為true,啟用本地調(diào)試:<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.      * 查找應(yīng)用服務(wù)器數(shù)據(jù)源,從數(shù)據(jù)源中獲得數(shù)據(jù)庫(kù)連接。<br><br>
          44.      * 在本地調(diào)試時(shí)如果查找數(shù)據(jù)源失敗并且enableLocalDebug==true
          45.      * 則根據(jù)系統(tǒng)屬性使用java.sql.DriverManager建立連接。<br>
          46.      * 本地調(diào)試時(shí)可配置的系統(tǒng)屬性如下:<br>
          47.      * <p>
          48.      *     #jdbc驅(qū)動(dòng)程序名 <br>
          49.      *     jdbc.driver=<i>oracle.jdbc.driver.OracleDriver</i> <br> <br>
          50.      *     #數(shù)據(jù)庫(kù)連接串<br>
          51.      *     jdbc.url=<i>jdbc:oracle:thin:@10.1.1.1:1521:ocrl</i> <br> <br>
          52.      *     #數(shù)據(jù)庫(kù)用戶名<br>
          53.      *     jdbc.username=<i>scott</i> <br> <br>
          54.      *     #數(shù)據(jù)庫(kù)用戶密碼<br>
          55.      *     jdbc.password=<i>tiger</i> <br>
          56.      * </p>
          57.      * 可通過(guò)JVM參數(shù)設(shè)置上述系統(tǒng)屬性:<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 如果數(shù)據(jù)源查找失敗
          63.      * @throws SQLException 如果建立數(shù)據(jù)庫(kù)連接失敗
          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.     //通過(guò)DriverManager建立本地測(cè)試連接
          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.      * 將查詢結(jié)果封裝成List。<br>
          100.      * List中元素類型為封裝一行數(shù)據(jù)的Map,Map key為字段名(大寫),value為相應(yīng)字段值
          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.      * 關(guān)閉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) 評(píng)論(0)  編輯  收藏 所屬分類: java 轉(zhuǎn)帖
          主站蜘蛛池模板: 思茅市| 临朐县| 建昌县| 西乌珠穆沁旗| 邯郸县| 齐河县| 东方市| 灵宝市| 云南省| 若尔盖县| 河东区| 桓仁| 洛宁县| 团风县| 抚远县| 镇坪县| 宁阳县| 博野县| 乐清市| 黔西县| 沽源县| 绍兴市| 惠州市| 温宿县| 锡林浩特市| 贞丰县| 左贡县| 东乌| 大安市| 太仆寺旗| 长岭县| 南通市| 商都县| 襄汾县| 商南县| 绵阳市| 龙泉市| 临汾市| 大化| 开远市| 永康市|