- Java Web開發實例大全(基礎卷) (軟件工程師開發大系)
- 軟件開發技術聯盟
- 7982字
- 2021-03-26 13:01:25
5.6 對數據庫操作的JavaBean
在開發程序的過程中經常會對數據庫進行操作,為了提高代碼的重用性,可以將對數據庫的操作封裝到一個單獨的類中。這樣既提高了代碼的重用性,又有利于程序的維護。
實例153 連接數據庫的方法
光盤位置:光盤\MR\05\153
初級
實用指數:
實例說明
本實例主要是獲得一個數據庫連接。運行本實例,如圖5.28所示,單擊“獲得連接”按鈕,若數據庫連接成功,則提示“獲取連接成功”,否則提示“獲取連接失敗”。

圖5.28 獲得數據庫的連接
關鍵技術
若要獲得一個數據庫連接,首先要加載數據庫的驅動程序,然后再使用DriverManager.getConnection()方法來獲得數據庫連接,具體語法格式如下:
DriverManager.getConnection(url, "sa", "")
功能:獲取數據庫連接實例對象。
參數說明
url:是數據庫的訪問路徑信息。例如,連接SQL Server 2005的URL格式如下:
jdbc:sqlserver://localhost:1433; DatabaseName=db_javabean
在使用上述方法獲得數據庫連接之前要設置驅動數據庫的類的路徑,具體語法格式如下:
Class.forName(classname)
功能:裝載數據庫的驅動類。
參數說明
classname:數據庫驅動類的路徑,如com.microsoft.sqlserver.jdbc.SQLServerDriver。
注意:在DriverManager.getConnection()方法中有3個參數:url為數據庫的URL地址,"sa"為登錄數據庫服務器的用戶名;若登錄服務器的密碼為空,用""表示。
設計過程
(1)為實現本實例,首先需要創建一個DB.java文件來處理數據庫的連接,關鍵代碼如下:
import java.sql.*; public class DB { private Connection con; private Statement stm; //用于執行SQL語句的Statement類的實例對象 private ResultSet rs; //結果集對象 private String classname="com.microsoft.sqlserver.jdbc.SQLServerDriver"; private String url ="jdbc:sqlserver://localhost:1433; DatabaseName=db_database05"; public DB(){ try{ Class.forName(classname); //加載驅動程序 }catch(ClassNotFoundException e){e.printStackTrace(); } } public Connection getCon(){ try{ con=DriverManager.getConnection(url, "sa", ""); //獲得連接 }catch(Exception e){ e.printStackTrace(System.err); con=null; } return con; } public void closed(){ try{ if(con! =null)con.close(); //關閉連接 }catch(Exception e){e.printStackTrace(); } }
(2)創建連接數據庫的首頁面index.jsp,關鍵代碼如下:
<form action="dogetcon.jsp"> <table> … <tr> <td align="center" height="60" valign="middle"> <input type="submit" value="獲得連接"> </td> </tr> </table> </form>
(3)新建一個dogetcon.jsp頁面,該頁面調用DB類來獲得一個數據庫連接。dogetcon.jsp頁面的關鍵代碼如下:
<%@ page contentType="text/html; charset=GBK"%> <%@ page import="java.sql.*"%> <jsp:useBean id="db" class="com.jb.db.DB" scope="page"/> <% … Connection con=db.getCon(); //調用DB類中的getCon()方法來獲得一個連接 … %>
秘笈心法
對數據庫的連接配置的連接URL、數據庫驅動類、數據庫名和數據庫密碼也可以寫在*.properties屬性文件中,然后應用java.util.Properties類來讀取這些屬性值,再進行創建數據庫的連接。當需要更換數據庫時,只修改屬性文件的配置即可,而不必每次都修改數據庫連接類的代碼,這樣更利于系統的維護管理。
實例154 數據庫查詢的方法
光盤位置:光盤\MR\05\154
初級
實用指數:
實例說明
在開發程序時,經常需要將數據庫中的信息顯示在網頁中以供用戶瀏覽和選擇,如圖5.29所示。那么如何將數據庫中的信息顯示在頁面上呢?本實例將解決這個問題。

圖5.29 數據的查詢
關鍵技術
通過調用Statement對象的executeQuery()方法來查詢數據表并得到一個查詢結果集,語法結構如下:
ResultSet rs=executeQuery(String sql)
功能:執行查詢語句并返回查詢結果。
參數說明
? sql:此參數是要執行的SQL語句。例如,本實例中查詢所有信息的SQL語句如下:
select*|字段名表from數據表名
? rs:此參數是ResultSet類的實例對象,它用于存儲從數據庫中查詢的結果集。
設計過程
(1)首先要獲得一個數據庫連接,然后才能對數據表進行查詢操作。在實例153中的DB類文件基礎上加入如下方法來實現數據的查詢,關鍵代碼如下:
public Statement getStm(){ try{ con=getCon(); stm=con.createStatement(); }catch(Exception e){e.printStackTrace(System.err); } return stm; } public Statement getStmed(){ try{ con=getCon(); stm=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); }catch(Exception e){e.printStackTrace(System.err); } return stm; } public ResultSet getAllRs(){ String sql="select * from tb_user"; try{ stm=getStmed(); rs=stm.executeQuery(sql); }catch(SQLException e){e.printStackTrace(); } return rs; }
(2)建立一個數據查詢的首頁面index.jsp,關鍵代碼如下:
<form name="searchform" method="post" action="dosearchall.jsp"> <table> <tr align="center" valign="middle" bgcolor="#CCCCCC" height="22"> <td>用戶名</td> <td>性別</td> <td>年齡</td> <td>職務</td> </tr> <! -- start --> <% ResultSet rs=(ResultSet)session.getAttribute("resultset"); … while(rs.next()){ %> <tr align="center" valign="middle" height="22"> <td><%=rs.getString("user_name") %></td> <td><%=rs.getString("user_sex") %></td> <td><%=rs.getInt("user_age") %></td> <td><%=rs.getString("user_job") %></td> </tr> <%}%> <! -- end --> <tr> <td align="center" colspan="4"> <input type="submit" name="searchall" value="查詢全部數據"> </td> </tr> </table> </form>
(3)建立接收Form表單的頁面dosearchall.jsp,在該頁面中進行數據查詢操作,關鍵代碼如下:
<%@ page contentType="text/html; charset=GBK"%> <%@ page import="java.sql.*" %> <jsp:useBean id="db" class="com.jb.db.DB" scope="page"/> <% ResultSet rs=db.getAllRs(); //獲得查詢的結果集 session.setAttribute("resultset", rs); //將得到的結果集存儲在session會話中 response.sendRedirect("index.jsp"); //返回到index.jsp頁面顯示數據信息 %>
秘笈心法
對于數據庫查詢方法的代碼,可以將它寫在一個類中,如果要查詢數據庫中一個表的多條數據,可以定義一個與表對應的JavaBean類,JavaBean類的屬性與表的字段相對應,然后在查詢方法中將查詢結果集的每一行數據封裝在JavaBean中,最后將這些封裝數據添加到java.util.List集合中。數據庫的查詢方法只返回一個封裝數據的List集合即可,然后在頁面中只需要調用這個方法,從而避免在JSP頁面中編寫大量對數據庫操作的Java代碼。
實例155 帶參數的數據查詢
光盤位置:光盤\MR\05\155
初級
實用指數:
實例說明
在瀏覽網頁時,經常需要得到符合某個條件的所有信息。本實例使用帶參數的查詢方法來實現查詢符合某一條件的所有信息。運行程序,在圖5.30所示的頁面中選擇“查詢類型”為“性別”,查詢關鍵字為“男”后,單擊“查詢”按鈕即可查詢所有性別為“男”的記錄,如圖5.31所示。

圖5.30 帶參數的數據查詢

圖5.31 查詢結果
關鍵技術
本實例主要應用了SQL的SELECT語句從數據庫中查詢符合條件的記錄,該SQL語句的具體語法格式如下:
select*|字段名表from數據表名where字段名=值
功能:查詢符合條件的數據記錄,代碼如下:
select * from tb_user where username='yxq'
設計過程
(1)在DB類中定義getPartRs(String subsql,Strig subsqlvalue)方法來查詢符合條件的記錄,并返回ResultSet類的結果集。getPartRs()方法的完整代碼如下:
…//省略了建立數據庫連接和獲得Statement對象的代碼 public ResultSet getPartRs(String subsql, String subsqlvalue){ if(subsql==null) subsql=""; if(subsqlvalue==null) subsqlvalue=""; String sql="select*from tb_user where"+subsql+"='"+subsqlvalue+"'"; //生成SQL語句 try{ stm=getStmed(); //獲取Statement對象 rs=stm.executeQuery(sql); //執行SQL語句,獲取結果集 }catch(SQLException e){e.printStackTrace(); } return rs; //返回結果集對象 }
(2)創建帶參數查詢的首頁面index.jsp,在該頁面中包含一個下拉列表框用來顯示查詢的條件,一個文本框供用戶輸入所要查詢的值,單擊“查詢”按鈕進行表單提交。此頁面的關鍵代碼如下:
<form name="searchform" method="post" action="dosearchpart.jsp"> <table> <tr bgcolor="lightgrey" height="25"> <td align="center">用戶名</td> <td align="center">性別</td> <td align="center">年齡</td> <td align="center">職務</td> <td align="center">資金</td> </tr> <% ResultSet rsall=db.getAllRs(); //獲得數據表中的所有記錄 while(rsall.next()){ //循環顯示出所有記錄 %> <tr> <td align="center"><%=rsall.getString("user_name")%></td> <td align="center"><%=rsall.getString("user_sex")%></td> <td align="center"><%=rsall.getInt("user_age")%></td> <td align="center"><%=rsall.getString("user_job")%></td> <td align="center"><%=rsall.getFloat("user_money")%></td> </tr> <% } %> <tr bgcolor="lightgrey"> <td align="center" colspan="5"> 查詢類型: <select name="subsql"> <option value="user_name">用戶名</option> <option value="user_sex">性別</option> <option value="user_age">年齡</option> <option value="user_job">職務</option> </select> <input type="text" name="subsqlvalue" size="17"> <input type="submit" name="searchpart" value="查詢" onclick="return check()"> </td> </tr> </table> </form>
(3)創建接收Form表單的dosearchpart.jsp頁面,在該頁面中調用DB類中的getPartRs()方法進行查詢,關鍵代碼如下:
<%@ page import="java.sql.*" %> <jsp:useBean id="db" class="com.jb.db.DB" scope="page"/> <% ResultSet rs=null; boolean mark=true; String mess=""; String subsql=request.getParameter("subsql"); //獲取用戶選擇的查詢類型 String subsqlvalue=request.getParameter("subsqlvalue"); //獲取用戶輸入的查詢條件 ……//省略部分代碼 %> <table> <tr> <td align="center" colspan="5"><%=mess%></td> </tr> <tr bgcolor="lightgrey" height="20"> <td align="center">用戶名</td> <td align="center">性別</td> <td align="center">年齡</td> <td align="center">職務</td> <td align="center">資金</td> </tr> <% subsqlvalue=new String(subsqlvalue.getBytes("ISO-8859-1")); rs=db.getPartRs(subsql, subsqlvalue); //調用getPartRs()方法進行帶參數的查詢操作 if(! rs.next()){ %> <tr> <td align="center"colspan="5">沒有記錄顯示!</td> </tr> <% } else{ rs.previous(); while(rs.next()){ %> <tr> <td align="center"><%=rs.getString("user_name")%></td> <td align="center"><%=rs.getString("user_sex")%></td> <td align="center"><%=rs.getInt("user_age")%></td> <td align="center"><%=rs.getString("user_job")%></td> <td align="center"><%=rs.getFloat("user_money")%></td> </tr> <% }//while } %> </table>
秘笈心法
如果知道結果集ResultSet中每個字段數據的索引,在應用ResultSet對象的getXXX()方法獲取數據時,也可以用索引指定,索引值是從1開始的。例如,獲取結果集中第二個字段的值,可以用getXXX(2)這種寫法。
實例156 向數據表中插入數據的方法
光盤位置:光盤\MR\05\156
初級
實用指數:
實例說明
大多數網站都有用戶注冊功能,當用戶填寫注冊信息(如圖5.32所示),單擊“添加”按鈕后,服務器將用戶輸入的信息添加到數據庫中,如圖5.33所示。

圖5.32 數據的增加

圖5.33 增加數據后的數據表
關鍵技術
實現數據的增加使用了insert into語句。該語句用于向數據庫中插入數據記錄,其語法格式有兩種,下面分別進行介紹。
語法1:
insert into數據表名(字段1,字段2, …字段n)values(值1,值2, …值n)
語法2:
若該語句中的字段與數據表中的字段的數目和結構都相同,則可以寫成下面的語句:
insert into數據表名values(值1,值2, …值n)
設置了增加數據的SQL語句后,還要使用Statement對象的executeUpdate()方法通過執行該SQL語句來實現向數據表中增加記錄。該方法的語法格式如下:
executeUpdate(String sql)
功能:執行SQL更新語句。
參數說明
sql:為向數據庫中增加數據的SQL語句。
設計過程
(1)在DB類中定義insert()方法用于執行向數據庫中插入記錄的SQL語句。在該方法中用到了getStmed()方法,可參見光盤中的相關代碼。insert()方法的完整代碼如下:
…//省略了建立數據庫連接和獲得Statement對象的代碼 public int insert(String sql){ int num=-1; if(sql==null)sql=""; try{ stm=getStmed(); num=stm.executeUpdate(sql); }catch(Exception e){e.printStackTrace(); num=-1; } return num; }
(2)創建接收Form表單數據的頁面doinsert.jsp,在該頁面中設置了SQL語句并進行增加操作,關鍵代碼如下:
<jsp:useBean id="db" class="com.jb.db.DB"/> <html> <head> <title>增加數據</title> <link rel="stylesheet" type="text/css" href="css/style.css"> </head> <% String mess=""; String username=request.getParameter("username"); …//省略了獲取其他屬性的代碼 float money=0; boolean mark=true; if(username==null||username.equals("")){ mark=false; mess="<li>請輸入<b>用戶名!</b></li>"; } …//省略了判斷其他屬性的代碼 if(mark){ try{ age=Integer.parseInt(userage); }catch(Exception e){mark=false; mess+="<li>輸入的<b>年齡</b>不是數字!</li>"; } try{ money=Float.parseFloat(usermoney); }catch(Exception e){mark=false; mess+="<li>輸入的<b>資金</b>不是數字!</li>"; } } if(mark){ username=new String(username.getBytes("ISO-8859-1"), "gbk"); usersex=new String(usersex.getBytes("ISO-8859-1"), "gbk"); userjob=new String(userjob.getBytes("ISO-8859-1"), "gbk"); String sql="insert into tb_user values('"+username+"', '"+usersex+"', "+age+", '"+userjob+"', "+money+")"; int i=db.insert(sql); db.closed(); if(i>0) response.sendRedirect("show.jsp"); else mess="插入失敗!"; } %> <table> <tr bgcolor="lightgrey"> <td>友情提示!</td> </tr> <tr> <td align="center"><%=mess%></td> </tr> </table>
秘笈心法
在獲取表單請求數據時,經常發生的問題就是中文亂碼,如果頁面的編碼格式不統一,就會發生這樣的問題。因此,在獲取表單請求數據之前,首先確定頁面的編碼格式是否一致,如表單頁的編碼格式為UTF-8,那么在獲取表單請求的處理頁或Servlet中,也應該設置編碼格式為UTF-8。
實例157 數據修改的方法
光盤位置:光盤\MR\05\157
初級
實用指數:
實例說明
任何網站都需要維護和更新數據庫中的數據,其中使用最頻繁的是對數據的修改操作,如論壇中需要提供用戶昵稱和頭像的修改或更新回帖的數量等。本實例主要實現的是修改數據庫中的某條記錄。如圖5.34所示,在“用戶名”文本框中輸入需要更新基本信息的用戶名并單擊“更新該用戶”按鈕,如果輸入的用戶名存在,則跳轉到showupdate.jsp頁面,如圖5.35所示。進行更新操作,更新后的結果如圖5.36所示,否則顯示提示信息。

圖5.34 更新前的用戶信息

圖5.35 填寫更新信息

圖5.36 更新后的用戶信息
關鍵技術
本實例調用了Statement對象的executeUpdate()方法執行SQL語句來實現數據的更新。實例中使用的SQL語句為更新(UPDATE)語句,語法格式如下:
UPDATE數據表名SET字段名=值[,字段名1=值1, …,字段名n=值n]where字段名=值
功能:更新數據表的數據。
設計過程
(1)在DB類中用定義update()方法來執行更新數據表的SQL語句。在該方法中用到的getStmed()方法的相關代碼可參見光盤。update()方法的完整代碼如下:
…//省略了建立數據庫連接和獲得Statement對象的代碼 public int update(String sql){ int num=-1; if(sql==null)sql=""; try{ stm=getStmed(); num=stm.executeUpdate(sql); }catch(Exception e){e.printStackTrace(); num=-1; } return num; }
(2)創建數據更新的首頁面index.jsp,該頁面要求用戶輸入要修改的用戶名,關鍵代碼如下:
<form action="dosearch.jsp" name="searchuserform"> <table> <tr bgcolor="lightgrey" height="25"> <td align="center">用戶名</td> <td align="center">性別</td> <td align="center">年齡</td> <td align="center">職務</td> <td align="center">資金</td> </tr> <% ResultSet rsall=db.getRs("select*from tb_user"); //執行SQL語句,獲取結果集 while(rsall.next()){ //循環結果集,顯示數據表中的所有信息 %> <tr> <td align="center"><%=rsall.getString("user_name")%></td> <td align="center"><%=rsall.getString("user_sex")%></td> <td align="center"><%=rsall.getInt("user_age")%></td> <td align="center"><%=rsall.getString("user_job")%></td> <td align="center"><%=rsall.getFloat("user_money")%></td> </tr> <% } %> <tr bgcolor="lightgrey"> <td colspan="1" align="center">用戶名:</td> <td colspan="3" align="cener"> <input type="text" name="searchusername"> </td> <td align="center" colspan="1"> <input type="submit" name="searchsubmit" value="更新該用戶" onclick="return searchcheck()"> </td> </tr> </table> </form>
(3)創建處理Form表單的頁面dosearch.jsp。在該頁面中查詢輸入的用戶名是否存在,如果存在,跳轉到showupdate.jsp頁面;否則顯示提示信息,關鍵代碼如下:
<%@ page import="java.sql.*" %> <jsp:useBean id="db" class="com.jb.db.DB"/> <% String mess=""; boolean mark=true; String username=request.getParameter("searchusername"); //獲取用戶輸入的姓名 if(username==null||username.equals("")){ mark=false; mess="<li>請輸入<b>用戶名!</b></li>"; } if(mark){ username=new String(username.getBytes("ISO-8859-1"), "gbk"); String sql="select*from tb_user where user_name='"+username+"'"; //按用戶名查詢表 ResultSet rs=db.getRs(sql); //獲取查詢結果集 if(rs.next()){ //遍歷查詢結果集 session.setAttribute("searchusername", rs.getString("user_name")); //將姓名保存在當前會話中 db.closed(); //關閉數據庫連接 response.sendRedirect("showupdate.jsp"); //跳轉到showupdate.jsp頁面 } else{ db.closed(); mess="您輸入的用戶名不存在!"; } } %> <table> <tr bgcolor="lightgrey"> <td>友情提示!</td> </tr> <tr> <td align="center"><%=mess%></td> </tr> </table>
(4)創建供用戶輸入更新信息的頁面showupdate.jsp,關鍵代碼如下:
<form action="doupdate.jsp" name="updateform"> <table> <tr> <td colspan="2" align="center" bgcolor="lightgrey"> 請填寫更新信息! </td> </tr> <tr> <td align="right">用戶名:</td> <td><%=(String)session.getAttribute("searchusername")%></td> </tr> <tr> <td align="right">性別:</td> <td><input type="text" name="usersex" maxlength="1"></td> </tr> …//省略了其他用戶信息的代碼 <tr> <td colspan="2" align="center"> <input type="submit" name="submit" value="更新" onclick="return check()"> <input type="reset" name="reset" value="重置"> </td> </tr> </table> </form>
(5)創建處理步驟(4)中Form表單的頁面doupdate.jsp。該頁面用來接收表單數據,并進行更新操作。如果更新成功,則跳轉到index.jsp頁面;否則顯示提示信息,關鍵代碼如下:
<jsp:useBean id="db" class="com.jb.db.DB"/> <% String mess=""; String username=(String)session.getAttribute("searchusername"); //獲取用戶名 String usersex=request.getParameter("usersex"); //性別 String userage=request.getParameter("userage"); //年齡 String userjob=request.getParameter("userjob"); //職位 String usermoney=request.getParameter("usermoney"); //資金 int age=0; float money=0; boolean mark=true; if(username==null||username.equals("")){ mark=false; mess="<li>請輸入<b>用戶名!</b></li>"; } …//省略了判斷其他屬性的代碼 if(mark){ try{ age=Integer.parseInt(userage); //轉換為整型 }catch(Exception e){mark=false; mess+="<li>輸入的<b>年齡</b>不是數字!</li>"; } try{ money=Float.parseFloat(usermoney); //資金轉換為浮點型 }catch(Exception e){mark=false; mess+="<li>輸入的<b>資金</b>不是數字!</li>"; } } if(mark){ usersex=new String(usersex.getBytes("ISO-8859-1"), "gbk"); userjob=new String(userjob.getBytes("ISO-8859-1"), "gbk"); String sql="update tb_user set user_sex='"+usersex+ "', user_age="+age+", user_job='"+userjob+ "', user_money="+money+"where user_name='"+username+"'"; //生成SQL語句 int i=db.update(sql); //執行SQL語句 db.closed(); //關閉數據庫連接 if (i<=0) mess="更新失敗!"; else{ session.invalidate(); response.sendRedirect("index.jsp"); } } %> <table> <tr bgcolor="lightgrey"> <td>友情提示!</td> </tr> <tr> <td align="center"><%=mess%></td> </tr> </table>
秘笈心法
在本實例實現的更新方法中,應用到的Statement接口可以改為PreparedStatement接口。應用PreparedStatement對SQL語句進行預編譯,這樣,在編寫SQL語句時,就可以用“?”占位符來代替直接編寫在SQL語句中的參數變量,然后再應用PreparedStatement的setXXX()方法為參數進行賦值,這樣可以避免SQL語句的注入式攻擊。
實例158 數據刪除的方法
光盤位置:光盤\MR\05\158
初級
實用指數:
實例說明
本實例實現刪除數據庫中的某條記錄的功能。運行本實例,在“用戶名”文本框中輸入yxq,如圖5.37所示,單擊“刪除該用戶”按鈕即可將該用戶刪除,刪除后的結果如圖5.38所示。

關鍵技術
本實例主要調用Statement對象的executeUpdate()方法執行SQL語句來實現數據的刪除。實例中使用的SQL語句為DELETE語句,具體語法格式如下:
delete from數據表名where字段名=值
功能:刪除數據表中的某條記錄。
設計過程
(1)在DB類中定義delete()方法執行刪除數據的SQL語句,完整代碼如下:
…//省略了建立數據庫連接的代碼 public int delete(String sql){ int num=0; if(sql==null)sql=""; try{ stm=getStmed(); num=stm.executeUpdate(sql); }catch(Exception e){e.printStackTrace(); num=-1; } return num; }
(2)創建刪除數據的首頁面index.jsp,關鍵代碼如下:
<form action="dodelete.jsp" name="deleteform"> <table> <tr bgcolor="lightgrey" height="25"> <td align="center">用戶名</td> <td align="center">性別</td> <td align="center">年齡</td> <td align="center">職務</td> <td align="center">資金</td> </tr> <% ResultSet rsall=db.getRs("select*from tb_user"); //查詢數據庫中的記錄 while(rsall.next()){ //顯示數據表中的所有記錄 %> <tr> <td align="center"><%=rsall.getString("user_name")%></td> <td align="center"><%=rsall.getString("user_sex")%></td> <td align="center"><%=rsall.getInt("user_age")%></td> <td align="center"><%=rsall.getString("user_job")%></td> <td align="center"><%=rsall.getFloat("user_money")%></td> </tr> <% } %> <tr bgcolor="lightgrey"> <td colspan="1" align="center">用戶名:</td> <td colspan="3" align="cener"> <input type="text" name="delusername"> </td> <td align="center" colspan="1"> <input type="submit" name="delsubmit" value="刪除該用戶" onclick="return check()"> </td> </tr> </table> </form>
(3)創建處理Form表單的頁面dodelete.jsp。該頁面進行數據刪除操作,如果刪除成功,則跳轉到index.jsp頁面;否則顯示提示信息,關鍵代碼如下:
<%@ page import="java.sql.*" %> <jsp:useBean id="db" class="com.jb.db.DB" scope="page"/> <% boolean mark=true; String mess=""; String username=request.getParameter("delusername"); if(username==null||username.equals("")){ mark=false; mess="<li>請輸入<b>用戶名!</b></li>"; } if(mark){ username=new String(username.getBytes("ISO-8859-1"), "gbk"); String sql="select * from tb_user where user_name='"+username+"'"; ResultSet rs=db.getRs(sql); if(! rs.next()){ mess="輸入的用戶名不存在!"; } else{ sql="delete from tb_user where user_name='"+username+"'"; //生成SQL語句 int num=db.delete(sql); //調用執行SQL語句的方法 db.closed(); //關閉數據庫連接 if(num>0) response.sendRedirect("index.jsp"); else mess="刪除失敗!"; } } %> <table> <tr> <td align="center"><%=mess%></td> </tr> </table>
秘笈心法
在實際應用中,一般都是根據ID來刪除表數據的,因為只有ID是唯一的,其他字段值都有可能存在重復,這樣可以避免誤刪除其他數據。本實例并沒有根據表的ID值來刪除數據,是由于此前設置了在添加用戶信息時,用戶名字段的值不能重復。讀者可以對本實例稍作改動,應用表的ID來實現刪除數據。
實例159 數據分頁的方法
光盤位置:光盤\MR\05\159
初級
實用指數:
實例說明
數據庫分頁是指通過查詢語句從數據庫中查詢出某頁所要顯示的數據。本實例將從數據庫中查詢出每個頁面需要顯示的記錄數。例如,某一數據表中有10條記錄,若以每頁4條記錄來進行顯示,在顯示第二頁信息時,只需查詢從第5條開始到第8條的所有記錄,實例運行結果如圖5.39所示。

圖5.39 數據庫的分頁顯示
關鍵技術
由于本實例使用的是SQL Server數據庫,而SQL Server對于查詢分頁的SQL語句主要應用的是Top關鍵字,具體代碼如下:
select top m * from tb_game where id>(select MAX(id) from(select top (n-1)*m (id) from tb_game) as maxid)
功能:查詢出只在當前頁需要顯示的所有記錄。
參數說明
? n為當前頁碼,m為每頁顯示的記錄數,id是一個被設為自動編號的初始值為1、增量為1的字段名。
? 子查詢語句1:“select top(n-1)*m (id) from tb_game”表示從tb_game表中查詢出第n頁前的所有記錄。
? 子查詢語句2:“select MAX(id) from(select top (n-1)*m (id) from tb_game) as maxid”表示從子查詢語句1中查詢出字段id中的最大值。
設計過程
(1)在對數據庫進行操作的DB類中定義如下屬性和方法,關鍵代碼如下:
private int num_per=4; //每頁顯示的記錄數 private int num_rs=0; //總記錄數 private int pages_all=0; //總頁數 private int page_current=1; //當前頁數 …//省略了建立數據庫連接和獲得Statement對象的代碼 public void setPageInfo(int page){ //在該方法中計算出總記錄數、總頁數 //并對通過參數傳遞的當前頁數進行判斷 String sql="select*from tb_user"; try{ stm=getStmed(); this.rs=stm.executeQuery(sql); this.rs.last(); //將記錄指針移動到最后一條記錄 this.num_rs=this.rs.getRow(); //獲取當前指針所指記錄的行號,即總記錄數 //計算出總頁數 this.pages_all=(num_rs%num_per==0)? (num_rs/num_per):(num_rs/num_per)+1 if(page<1) //由參數傳遞過來的當前頁數值如果小于1,則將當前頁數設置為1 this.page_current=1; else if(page>pages_all) //由參數傳遞過來的當前頁數值如果大于總頁數,則將當前頁數設置為總頁數 this.page_current=this.pages_all; else this.page_current=page; }catch(SQLException e){e.printStackTrace(); } } public ResultSet getPageRs(){ //數據庫分頁顯示的關鍵代碼 int idnum=(this.page_current-1)*this.num_per; //第n頁之前的記錄數 String sql=""; if(this.page_current==1) //判斷是否為第一頁 sql="select top "+this.num_per+" * from tb_game"; else sql="select top "+this.num_per+" * from tb_game where id>(select MAX(id) from(select top "+idnum+" (id) from tb_game) as maxid)"; try{ rs=stm.executeQuery(sql); }catch(Exception e){e.printStackTrace(); } return rs; } public int getNumper(){ //返回每頁顯示記錄數的方法 return this.num_per; } public int getNumrs(){ //返回總記錄數的方法 return this.num_rs; } public int getPagesall(){ //返回總頁數的方法 return this.pages_all; } public int getPagecurrent(){ //返回當前頁數的方法 return this.page_current; }
(2)創建分頁顯示的首頁面index.jsp,關鍵代碼如下:
<%@ page import="java.sql.*, com.jb.db.DB" %> <% DB db=new DB(); %> <form name="searchform" method="post" action="dopagedb.jsp"> <table> <tr align="center" valign="middle" bgcolor="#CCCCCC" height="22"> <td>游戲名</td> <td>人氣</td> <td>大小</td> <td>上傳者</td> </tr> <% ResultSet rs=(ResultSet)session.getAttribute("pageresultset"); if(rs==null){ %> <tr align="center" valign="middle"><td colspan="4">沒有記錄顯示!</td> </tr> <% } else{ db=(DB)session.getAttribute("db"); while(rs.next()){ %> <tr align="center" valign="middle" height="22"> <td><%=rs.getString("game_name") %></td> <td><%=rs.getString("game_hot") %></td> <td><%=rs.getString("game_size") %></td> <td><%=rs.getString("game_uper") %></td> </tr> <% } %> <tr bgcolor="lightgrey"> <td colspan="4" align="center"> 每頁:<%=db.getNumper()%>/<%=db.getNumrs()%> 條記錄 當前頁:<%=db.getPagecurrent()%>/<%=db.getPagesall()%> 頁 </td> </tr> <% } %> <tr> <td align="center"colspan="4"> <input type="submit"name="searchall"value="查詢第一頁"> </td> </tr> //以下為顯示分頁導航信息的代碼 <%if(db.getPagesall()>1){%> <tr bgcolor="lightgrey"> <td align="center"colspan="4"> <%if(db.getPagecurrent()>1){%> <a href="dopagedb.jsp? currentpage=1">第一頁</a> <a href="dopagedb.jsp? currentpage=<%=db.getPagecurrent()-1%>">上一頁</a> <%}%> <%if(db.getPagecurrent()<db.getPagesall()){%> <a href="dopagedb.jsp? currentpage=<%=db.getPagecurrent()+1%>">下一頁</a> <a href="dopagedb.jsp? currentpage=<%=db.getPagesall()%>">最后一頁</a> <%}%> </td> </tr> <%}%> </table> </form>
(3)創建處理Form表單的頁面dopagedb.jsp,關鍵代碼如下:
<%@ page import="java.sql.*" %> <jsp:useBean id="db" class="com.jb.db.DB" scope="page"/> <% String strpage=request.getParameter("currentpage"); //獲取當前要顯示的頁碼 if(strpage==null||strpage.equals("")) strpage="1"; //默認為第一頁 int currentpage=1; try{ currentpage=Integer.parseInt(strpage); }catch(Exception e){currentpage=1; } db.setPageInfo(currentpage); ResultSet rs=db.getPageRs(); //獲取當前頁面要顯示的內容 session.setAttribute("db", db); //將db對象保存到當前會話中 session.setAttribute("pageresultset", rs); //將查詢結果集保存到當前會話對象中 response.sendRedirect("index.jsp"); //跳轉到index.jsp頁面 %>
秘笈心法
在本實例的dopagedb.jsp頁面中,將db對象放入session會話中是為了在返回到index.jsp頁面后能夠使用同一個db對象,而不是重新實例化一個DB類對象。如果想在不同JSP頁之間使用同一個JavaBean實例,讀者還可以在使用<jsp:useBean/>標簽時將scope屬性設置為session范圍。
實例160 對結果集進行分頁的方法
光盤位置:光盤\MR\05\160
初級
實用指數:
實例說明
本實例講解的是將用戶查詢到的所有的信息進行分頁顯示。例如,數據表中有10條記錄,以每頁4條記錄進行顯示,若要顯示第二頁的信息,首先應查詢出所有的記錄,然后在查詢出的全部記錄中查找要顯示第二頁信息的開始位置。如圖5.40所示,當用戶單擊“查詢全部數據”按鈕后,程序將查詢出來的數據存儲到ResultSet結果集中,然后單擊“下一頁”超鏈接,從該結果集中查找起始位置并顯示出相應的信息。

圖5.40 數據庫分頁顯示
關鍵技術
本實例根據當前的頁數來確定結果集中記錄指針的位置。該位置可以通過下面的算法得到:(當前頁數-1)*每頁顯示的記錄數+1。得到該位置后就可以使用ResultSet對象的absolute(int pos)方法來移動記錄指針至指定位置。
設計過程
(1)DB類的關鍵代碼如下:
private int num_per=4; //每頁顯示的記錄數
private int num_rs=0; //總記錄數
private int pages_all=0; //總頁數
private int page_current=1; //當前頁數
…//省略了建立數據庫連接的代碼
public Statement getStmed(){
try{
con=getCon();
stm=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); //只讀模式
}catch(Exception e){e.printStackTrace(System.err); }
return stm; //返回Statement對象
}
public void setPageInfo(int page){
String sql="select*from tb_user"; //聲明SQL語句
try{
stm=getStmed(); //獲取Statement對象
this.rs=stm.executeQuery(sql); //執行SQL語句
this.rs.last(); //將記錄指針移動到最后一條記錄
this.num_rs=this.rs.getRow(); //獲取當前指針所指記錄的行號,即總記錄數
//計算出總頁數
this.pages_all=(num_rs%num_per==0)? (num_rs/num_per):(num_rs/num_per)+1;
if(page<1) //由參數傳遞過來的當前頁數值如果小于1,則將當前頁數設置為1
this.page_current=1;
else if(page>pages_all) //由參數傳遞過來的當前頁數值如果大于總頁數,則將當前頁數設置為總頁數
this.page_current=this.pages_all;
else
this.page_current=page;
}catch(SQLException e){e.printStackTrace(); }
}
public ResultSet getPageRs(){ //對結果集進行分頁顯示的關鍵代碼
try{
int pos=(this.page_current-1)*this.num_per+1; //設置記錄指針要移到的位置
this.rs.absolute(pos); //將結果集記錄指針移動到指定位置
}catch(Exception e){e.printStackTrace(); }
return this.rs;
}
(2)創建分頁顯示的首頁面index.jsp,關鍵代碼如下:
<form name="searchform" method="post" action="dopagers.jsp"> <table> <tr align="center" valign="middle" bgcolor="#CCCCCC" height="22"> <td>用戶名</td> <td>性別</td> <td>年齡</td> <td>職務</td> </tr> //如果session會話中不存在ResultSet對象 <tr align="center" valign="middle"> <td colspan="4">沒有記錄顯示!</td> </tr> //否則 <% db=(DB)session.getAttribute("db"); int i=1; //變量i用來控制顯示的記錄數 rs.previous(); //將指針移動到當前所指記錄的前面,否則在下面調用next()方法時將錯過一條記錄 while(rs.next()&&i<=db.getNumper()){ %> <tr align="center" valign="middle" height="22"> <td><%=rs.getString("user_name") %></td> <td><%=rs.getString("user_sex") %></td> <td><%=rs.getInt("user_age") %></td> <td><%=rs.getString("user_job") %></td> </tr> <% i++; } %> …//此處省略了顯示分頁信息的代碼 <tr> <td align="center" colspan="4"> <input type="submit" name="searchall" value="查詢全部數據"> </td> </tr> …//此處省略了顯示分頁導航信息的代碼 </table> </form>
(3)創建處理Form表單的頁面dopagers.jsp,關鍵代碼如下:
<jsp:useBean id="db" class="com.jb.db.DB" scope="page"/> <% String strpage=request.getParameter("currentpage"); //獲取要顯示的頁碼 if(strpage==null||strpage.equals(""))strpage="1"; int currentpage=1; try{ currentpage=Integer.parseInt(strpage); }catch(Exception e){currentpage=1; } db.setPageInfo(currentpage); ResultSet rs=db.getPageRs(); //調用getPageRs()方法來設置記錄指針移至指定位置 session.setAttribute("db", db); //將一個實例化的DB類對象放入session會話中 session.setAttribute("pageresultset", rs); //將設置好的結果集放入session會話中 response.sendRedirect("index.jsp"); //返回到index.jsp頁面 %>
秘笈心法
在本實例中,通過Statement對象的executeQuery(String sql)方法得到的結果集必須是可滾動的。也就是說,在本實例中Statement對象是通過調用DB類中的自定義方法getStmed()得到的,通過該方法得到的Statement對象才可以獲得可滾動的結果集。
實例161 關閉數據庫的方法
光盤位置:光盤\MR\05\161
初級
實用指數:
實例說明
數據庫連接是一個占用資源很大的操作,所以在對數據庫的操作結束后,應及時關閉連接。本實例將介紹如何關閉數據庫連接,實例運行效果如圖5.41所示。

圖5.41 關閉數據庫
關鍵技術
關閉數據庫連接,主要調用的是java.sql.Connection接口的close()方法。關閉數據庫連接的目的,就是為了釋放數據庫連接所占用的系統資源。
設計過程
(1)在對數據庫進行操作的DB類中定義如下方法,關鍵代碼如下:
…//省略了建立數據庫連接和獲得Statement對象的代碼 public void closed(){ try{ if(rs! =null)rs.close(); //關閉rs對象 }catch(Exception e){e.printStackTrace(); } try{ if(stm! =null)stm.close(); //關閉stm對象 }catch(Exception e){e.printStackTrace(); } try{ if(con! =null)con.close(); //關閉con對象 } catch(Exception e){e.printStackTrace(); } }
(2)創建關閉數據庫的首頁面index.jsp,關鍵代碼如下:
<script language="javascript"> function change(){ document.connectionform.action="doclose.jsp"; } </script> … <form action="dogetcon.jsp" name="connectionform"> <table> <tr><td>此處為顯示當前連接狀態代碼(省略)</td></tr> <tr> <td align="center" height="60" valign="middle"> <input type="submit" name="create" value="獲得連接"> <input type="submit" name="close" value="關閉連接" onclick="change()"> </td> </tr> </table> </form>
(3)創建一個用來關閉連接的頁面doclose.jsp,關鍵代碼如下:
<jsp:useBean id="db" class="com.jb.db.DB" scope="page"/> <% Connection con=(Connection)session.getAttribute("con"); if(con! =null){ db.closed(); session.setAttribute("closestatus", "連接已成功關閉!"); session.removeAttribute("con"); } else{ session.setAttribute("closestatus", "當前狀態沒有連接!"); } session.setAttribute("formname", "close"); response.sendRedirect("index.jsp"); %>
秘笈心法
在程序開發中,當對數據庫的操作結束后應及時調用該方法來關閉數據庫連接,以釋放所占用的系統資源。
實例162 數據庫事務處理的方法
光盤位置:光盤\MR\05\162
初級
實用指數:
實例說明
事務就是將多個操作封裝到一個單元中,且該單元不可再分。該事務中的多個操作要么都被執行,要么都不被執行。最常見的就是不同的賬戶間進行轉賬的例子,如圖5.42所示,“雨飛”用戶轉賬50元至“許久”用戶,可通過兩條更新語句來實現。若不使用事務處理,假設更新用戶“雨飛”的操作成功,那么“雨飛”的賬戶上將減少50元,如果在更新“許久”用戶的操作中出現錯誤,那么“許久”用戶的賬戶上并沒有加上從“雨飛”賬戶上轉過來的50元,這就失去了準確性。當出現上面的情況時,就可以用事務回滾的方法來撤銷剛剛提交的事務,恢復到未操作之前的狀態。

圖5.42 數據庫事務處理
關鍵技術
當獲得一個Connection對象后,調用它的getAutoCommit()方法可得到一個boolean類型的值,該值默認為true表示自動提交事務。若要使用事務處理需調用Connection對象的setAutoCommit(false)方法設置該值為false,然后再調用Connection對象的commit()方法來提交事務。若操作失敗,就可調用Connection對象的rollback()方法來回滾上次的操作。
設計過程
(1)在對數據庫進行操作的DB類中定義doback()方法,關鍵代碼如下:
…//省略了建立數據庫連接的代碼 public String doback(String from, String to, float money){ String mark=""; …//此處為查詢輸入的用戶名是否存在的代碼 fromsql="update tb_user set user_money=user_money-"+money+" where user_name='"+from+"'"; tosql="update tb_user set user_money=user_money+"+money+" where user_name='"+to+""; try{ con=getCon(); //獲得一個連接 con.setAutoCommit(false); //設置為禁止自動執行 stm=con.createStatement(); stm.execute(fromsql); //執行SQL語句1 stm.execute(tosql); //執行SQL語句2 con.commit(); //開始執行 mark="success"; //操作成功,返回success } catch(Exception e){ e.printStackTrace(); mark="false"; //操作失敗,返回false try{ con.rollback(); //回滾到上次操作之前 }catch(Exception ee){ee.printStackTrace(); } } return mark; }
(2)創建數據庫事務處理的首頁面index.jsp,關鍵代碼如下:
<form action="dorollback.jsp" name="dorollbackform"> <table> <tr align="center" height="25" bgcolor="lightgrey"> <td colspan="2" align="center">數據庫事務處理的方法</td> </tr> <tr> <td align="right">來源:</td> <td><input type="text" name="from"></td> </tr> <tr> <td align="right">轉至:</td> <td><input type="text" name="to"></td> </tr> <tr> <td align="right">金額:</td> <td><input type="text" name="money" size="10"> 元</td> </tr> <tr align="center" bgcolor="lightgrey"> <td colspan="2"> <input type="submit" name="Submit" value="轉賬" onclick="return check()"> </td> </tr> </table> </form>
(3)創建接收Form表單的頁面dorollback.jsp。該頁面調用DB類中的doback()方法進行轉賬操作,關鍵代碼如下:
<%@ page import="java.sql.*" %> <jsp:useBean id="db" class="com.jb.db.DB"/> <% boolean mark=true; String mess=""; float money=0; String fromname=request.getParameter("from"); String toname=request.getParameter("to"); String strmoney=request.getParameter("money"); if(fromname==null||fromname.equals("")){ mark=false; mess+="<li>請輸入<b>來源用戶!</b>"; } …//省略了判斷其他屬性的代碼 if(mark){ try{ money=Float.parseFloat(strmoney); }catch(Exception e){mark=false; mess="輸入的金額不是數字!"; } } if(mark){ fromname=new String(fromname.getBytes("ISO-8859-1"), "gbk"); toname=new String(toname.getBytes("ISO-8859-1"), "gbk"); String result=db.doback(fromname, toname, money); //調用事務處理 if(result.equals("success")) mess="轉賬成功!"; else if(result.equals("false")) mess="轉賬失敗!"; else mess=result; } %>
秘笈心法
為了保證數據的統一完整性,應該在對數據庫操作時及時應用事務來處理,保證在數據發生錯誤時取消操作,從而避免不必要的損失。
實例163 調用數據庫存儲過程的方法
光盤位置:光盤\MR\05\163
初級
實用指數:
實例說明
存儲過程是由存儲在數據庫管理系統中的一段SQL語句組成的一個過程。本實例通過向數據庫中增加記錄來講解如何建立及使用存儲過程,運行結果如圖5.43所示。

圖5.43 填寫用戶信息
關鍵技術
本實例主要通過CallableStatement對象來設置語句中的參數并執行調用。CallableStatement對象是通過Connection對象的prepareCall()方法得到的,語法格式如下:
prepareCall(String sql)
功能:獲得CallableStatement對象。
參數說明
sql:表示調用存儲過程的語句。
該方法將調用存儲過程的對象CallableStatement與調用語句關聯起來。其中調用語句的格式為{call存儲過程名(?,?,…,?)},它是調用存儲過程的通用格式。
設計過程
(1)首先在數據庫服務器上新建一個增加記錄的存儲過程,關鍵代碼如下:
CREATE PROCEDURE proc_add ( @username varchar(50), @usersex varchar(2), @userage int, @userjob varchar(50), @usermoney float) AS insert into tb_user values(@username, @usersex, @userage, @userjob, @usermoney) GO
說明:針對應用數據庫的不同,其存儲過程的語法結構可能存在差異,此存儲過程的語法規則為SQL Server數據庫中的寫法。
(2)在對數據庫進行操作的DB類中定義如下方法,關鍵代碼如下:
…//省略了建立數據庫連接和獲得Statement對象的代碼 public int useproc(String name, String sex, int age, String job, float money){ int num=-1; String procsql="{call proc_add(? , ? , ? , ? , ? )}"; //調用存儲過程 try{ con=getCon(); CallableStatement stm=con.prepareCall(procsql); //創建一個對象 stm.setString(1, name); //設置調用語句中的參數 stm.setString(2, sex); stm.setInt(3, age); stm.setString(4, job); stm.setFloat(5, money); num=stm.executeUpdate(); //執行調用 } catch(Exception e){e.printStackTrace(); num=-1; } return num; }
(3)調用存儲過程向數據庫中增加記錄,其首頁面設計與實例162的設計完全相同,讀者可參看該實例的頁面代碼。
(4)創建接收首頁面index.jsp中Form表單的頁面douseproc.jsp,關鍵代碼如下:
<%@ page import="java.sql.*" %> <jsp:useBean id="db" class="com.jb.db.DB"/> <% String mess=""; String username=request.getParameter("username"); String usersex=request.getParameter("usersex"); String userage=request.getParameter("userage"); String userjob=request.getParameter("userjob"); String usermoney=request.getParameter("usermoney"); int age=0; float money=0; boolean mark=true; if(username==null||username.equals("")){ mark=false; mess="<li>請輸入<b>用戶名!</b></li>"; } …//省略了判斷其他屬性的代碼 if(mark){ try{ age=Integer.parseInt(userage); }catch(Exception e){mark=false; mess+="<li>輸入的<b>年齡</b>不是數字!</li>"; } try{ money=Float.parseFloat(usermoney); }catch(Exception e){mark=false; mess+="<li>輸入的<b>資金</b>不是數字!</li>"; } } if(mark){ username=new String(username.getBytes("ISO-8859-1"), "gbk"); usersex=new String(usersex.getBytes("ISO-8859-1"), "gbk"); userjob=new String(userjob.getBytes("ISO-8859-1"), "gbk"); int i=db.useproc(username, usersex, age, userjob, money); db.closed(); if(i<0){ mess="操作失敗!"; } else mess="操作成功!"; } %>
秘笈心法
使用存儲過程可以加快程序的執行速度,因為存儲過程是預編譯的,所以使用執行SQL語句的方法可節省SQL語句的編譯時間;另外,還可以減少網絡數據傳輸的信息量,因為存儲過程是保留在數據庫服務器中的。