JSP頁面查詢顯示常用模式
title:?JSP頁面查詢顯示常用模式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對象時也需要很多額外的代碼。
示例代碼:
- //查詢數據代碼
- ??Connection?conn?=?DBUtil.getConnection();
- ??PreparedStatement?pst?=?null;
- ??ResultSet?rs?=?null;
- ??try{
- ????String?sql=“select?emp_code,?real_name?from?t_employee?where?organ_id=?”;
- ????pst?=?conn.preparedStatement(sql);
- ????pst.setString(1,?“101”);
- ????ResultSet?rs?=?pst.executeQuery();
- ????List?list?=?new?ArrayList();
- ????Employee?emp;
- ????while?(rs.next()){
- ??????emp?=?new?Employee();
- ??????emp.setReakName(rs.getString(“real_name”));
- ??????emp.setEmpCode(rs.getString(“emp_code”));
- ??????…
- ??????list.add(emp);
- ????}
- ????return?list;
- ??}finally{
- ????DBUtil.close(rs,?pst?,conn);
- ??}
- //jsp顯示部分代碼
- <%
- ??List?empList?=?(List)request.getAttribute(“empList”);
- ??if?(empList?==?null)?empList?=?Collections.EMPTY_LIST;
- %>
- …
- <table??cellspacing="0"?width=”90%”>
- ????<tr>??<td>代碼</td>?<td>姓名</td>??</tr>
- <%
- ??Employee?emp;
- ??for?(int?i=0;?i<?empList.size();?i++){
- ????emp?=?(Employee)?empList.get(i);
- %>
- ????<tr>??
- ??????<td><%=?emp.getEmpCode()%></td>?
- ??????<td><%=?emp.getRealName()%></td>??
- ????</tr>
- <%
- ??}//?end?for
- %>
- </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)方法中實現了上述過程(所有列名均使用大寫),可參考使用。
示例代碼:
- //查詢數據部分代碼:
- ??…
- ??Connection?conn?=?DBUtil.getConnection();
- ??PreparedStatement?pst?=?null;
- ??ResultSet?rs?=?null;
- ??try{
- ????String?sql=“select?emp_code,?real_name?from?t_employee?where?organ_id=?”;
- ????pst?=?conn.preparedStatement(sql);
- ????pst.setString(1,?“101”);
- ????rs?=?pst.executeQuery();
- ????List?list?=?DBUtil.?resultSetToList(ResultSet?rs);
- ????return?list;
- ??}finally{
- ????DBUtil.close(rs,?pst?,conn);
- ??}
- //JSP顯示部分代碼
- <%
- ??List?empList?=?(List)request.getAttribute(“empList”);
- ??if?(empList?==?null)?empList?=?Collections.EMPTY_LIST;
- %>
- …
- <table??cellspacing="0"?width=”90%”>
- ????<tr>??<td>代碼</td>?<td>姓名</td>??</tr>
- <%
- ??Map?colMap;
- ??for?(int?i=0;?i<?empList.size();?i++){
- ????colMap?=?(Map)?empList.get(i);
- %>
- ??<tr>??
- ????<td><%=colMap.get(“EMP_CODE”)%></td>?
- ????<td><%=colMap.get(“REAL_NAME”)%></td>??
- ??</tr>
- <%
- ??}//?end?for
- %>
- </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
示例代碼:
- //查詢數據部分代碼:
- ??import?javax.sql.RowSet;
- ??import?oracle.jdbc.rowset.OracleCachedRowSet;
- ??…
- ??Connection?conn?=?DBUtil.getConnection();
- ??PreparedStatement?pst?=?null;
- ??ResultSet?rs?=?null;
- ??try{……
- ????String?sql=“select?emp_code,?real_name?from?t_employee?where?organ_id=?”;
- ????pst?=?conn.preparedStatement(sql);
- ????pst.setString(1,?“101”);
- ????rs?=?pst.executeQuery();
- ????OracleCachedRowSet?ors?=?newOracleCachedRowSet();
- ????//將ResultSet中的數據封裝到RowSet中
- ????ors.populate(rs);
- ????return?ors;
- ??}finally{
- ????DBUtil.close(rs,?pst,?conn);
- ??}
- //JSP顯示部分代碼
- <%
- ??javax.sql.RowSet?empRS?=?(javax.sql.RowSet)?request.getAttribute(“empRS”);
- %>
- …
- <table??cellspacing="0"?width=”90%”>
- ????<tr>??<td>代碼</td>?<td>姓名</td>??</tr>
- <%
- ??if?(empRS?!=?null)?while?(empRS.next()?)?{
- %>
- ??<tr>??
- ????<td><%=?empRS.get(“EMP_CODE”)%></td>?
- ????<td><%=?empRS.get(“REAL_NAME”)%></td>??
- ??</tr>
- <%
- ??}//?end?while
- %>
- </table>
適用場合:
??方法一使用于定制的查詢操作
??方法二適用于多條查詢語句或需要對查詢結果進行處理的情況。
??方法三適合于單條查詢語句,適用于快速開發。
相關鏈接:
????如果需要分頁顯示請參考:JSP分頁技術實現
????如果查詢結果需要生成WORD或者EXCEL,請參考:使用jsp實現word、excel格式報表打印
附:DBUtil代碼:
- import?java.util.List;
- import?java.util.ArrayList;
- import?java.util.Map;
- import?java.util.HashMap;
- import?java.util.Properties;
- import?java.util.Collections;
- import?java.sql.Connection;
- import?java.sql.SQLException;
- import?java.sql.ResultSet;
- import?java.sql.ResultSetMetaData;
- import?java.sql.Statement;
- import?java.sql.PreparedStatement;
- import?javax.naming.Context;
- import?javax.naming.InitialContext;
- import?javax.naming.NamingException;
- import?javax.sql.DataSource;
- public?class?DBUtil{
- ????private?static?final?String?JDBC_DATA_SOURCE?=?"java:comp/env/jdbc/DataSource";
- ????/**
- ?????enableLocalDebug:?是否在本地調試。<br>
- ?????值為true時如果查找數據源失敗則使用DriverManager與數據庫建立連接;
- ?????如果為false則只查找數據源建立數據庫連接。
- ?????默認為false。<br>
- ?????可通過系統屬性jdbc.enable_local_debug=true設置enableLocalDebug為true,啟用本地調試:<br>
- ?????增加JVM?parameter:?-Djdbc.enable_local_debug=true
- ?????*/
- ????private?static?boolean?enableLocalDebug?=?false;
- ????static{
- ????????enableLocalDebug?=?Boolean.getBoolean?("jdbc.enable_local_debug");
- ????}
- ????private?static?Context?ctx?=?null;
- ????private?static?javax.sql.DataSource?ds?=?null;
- ????private?static?void?initDataSource()?throws?Exception{
- ????????//?Put?connection?properties?in?to?a?hashtable.
- ????????if?(ctx?==?null)?{
- ????????????ctx?=?new?InitialContext();
- ????????}
- ????????if?(ds?==?null)?{
- ????????????ds?=?(javax.sql.DataSource)?ctx.lookup(JDBC_DATA_SOURCE);
- ????????}
- ????}????????
- ????/**
- ?????*?查找應用服務器數據源,從數據源中獲得數據庫連接。<br><br>
- ?????*?在本地調試時如果查找數據源失敗并且enableLocalDebug==true
- ?????*?則根據系統屬性使用java.sql.DriverManager建立連接。<br>
- ?????*?本地調試時可配置的系統屬性如下:<br>
- ?????*?<p>
- ?????*?????#jdbc驅動程序名?<br>
- ?????*?????jdbc.driver=<i>oracle.jdbc.driver.OracleDriver</i>?<br>?<br>
- ?????*?????#數據庫連接串<br>
- ?????*?????jdbc.url=<i>jdbc:oracle:thin:@10.1.1.1:1521:ocrl</i>?<br>?<br>
- ?????*?????#數據庫用戶名<br>
- ?????*?????jdbc.username=<i>scott</i>?<br>?<br>
- ?????*?????#數據庫用戶密碼<br>
- ?????*?????jdbc.password=<i>tiger</i>?<br>
- ?????*?</p>
- ?????*?可通過JVM參數設置上述系統屬性:<br>
- ?????*?-Djdbc.driver=oracle.jdbc.driver.OracleDriver?
- ?????*??-Djdbc.url=jdbc:oracle:thin:@10.1.1.1:1521:ocrl
- ?????*??-Djdbc.username=scott?-Djdbc.password=tiger
- ?????*?@return?Connection
- ?????*?@throws?NamingException?如果數據源查找失敗
- ?????*?@throws?SQLException?如果建立數據庫連接失敗
- ?????*/
- ????public?static?Connection?getConnection()?throws??SQLException{
- ????????try{
- ????????????initDataSource();
- ????????????return?ds.getConnection();
- ????????}catch(SQLException?sqle){
- ????????????throw?sqle;
- ????????}catch(Exception?ne){
- ????????????if?(enableLocalDebug){
- ????????????????return?getTestConn();
- ????????????}else{
- ????????????????throw?new?RuntimeException(ne.toString());
- ????????????}
- ????????}
- ????}
- ????//通過DriverManager建立本地測試連接
- ????private?static?Connection?getTestConn(){
- ??????try?{
- ??????????String?driver?=?System.getProperty("jdbc.driver");
- ??????????System.out.println("jdbc.driver="+driver);
- ??????????String?url?=?System.getProperty("jdbc.url");
- ??????????System.out.println("jdbc.url="+url);
- ??????????String?userName?=?System.getProperty("jdbc.username");
- ??????????System.out.println("jdbc.username="+userName);
- ??????????String?password?=?System.getProperty("jdbc.password");
- ??????????System.out.println("jdbc.password="+password);
- ??????????Class.forName(driver).newInstance();
- ??????????return?java.sql.DriverManager.getConnection(url,?userName,?password);
- ??????}
- ??????catch?(Exception?ex)?{
- ????????ex.printStackTrace();
- ????????throw?new?RuntimeException(ex.getMessage());
- ??????}
- ????}
- ????/**
- ?????*?將查詢結果封裝成List。<br>
- ?????*?List中元素類型為封裝一行數據的Map,Map?key為字段名(大寫),value為相應字段值
- ?????*?@param?rs?ResultSet
- ?????*?@return?List
- ?????*?@throws?java.sql.SQLException
- ?????*/
- ????public?static?List?resultSetToList(ResultSet?rs)?throws?java.sql.SQLException{
- ????????if?(rs==null)?return?Collections.EMPTY_LIST;
- ????????ResultSetMetaData?md?=?rs.getMetaData();
- ????????int?columnCount?=?md.getColumnCount();
- ????????List?list?=?new?ArrayList();
- ????????Map?rowData;
- ????????while?(rs.next()){
- ????????????rowData?=?new?HashMap(columnCount);
- ????????????for?(int?i=1;?i<=columnCount;?i++){
- ????????????????rowData.put(md.getColumnName(i),rs.getObject(i));
- ????????????}
- ????????????list.add(rowData);
- ????????}
- ????????return?list;
- ????}
- ????/**
- ?????*?關閉ResultSet、Statement和Connection
- ?????*?@param?rs?ResultSet?to?be?closed
- ?????*?@param?stmt?Statement?or?PreparedStatement??to?be?closed
- ?????*?@param?conn?Connection??to?be?closed
- ?????*/
- ????public?static?void?close(ResultSet?rs,?Statement?stmt,?Connection?conn){
- ????????????if?(rs?!=?null)?try{
- ????????????????rs.close();
- ????????????}catch(java.sql.SQLException?ex){
- ????????????????ex.printStackTrace();
- ????????????}
- ????????????if?(stmt?!=?null)?try{
- ?????????????????stmt.close();
- ????????????}catch(java.sql.SQLException?ex){
- ????????????????ex.printStackTrace();
- ????????????}
- ????????????if?(conn?!=?null)?try{
- ????????????????conn.close();
- ????????????}catch(java.sql.SQLException?ex){
- ????????????????ex.printStackTrace();
- ????????????}
- ????}
- }//?end?of?DBUtil
posted on 2006-04-13 17:34 都市淘沙者 閱讀(1497) 評論(0) 編輯 收藏 所屬分類: JSP/PHP