<b>教</b><b> </b><b>學</b><b> </b><b>活</b><b> </b><b>動</b><b> </b><b>首</b><b> </b><b>頁</b><b> </b>
<b> </b>
<b>基</b><b> </b><b>本</b><b> </b><b>内</b><b> </b><b>容</b><b> </b>
第 5 章 jsp 中使用資料庫<b> </b>
<b>教學目的與要求:</b>通過本章的學習讓學生了解資料源的設定過程;了解jdbc-odbc 橋接器的工作原理,連接配接資料庫的其他方式,查詢 excel 電子表格;掌握查詢記錄,更新記錄,添加記錄,删除記錄的操作方法;并能實作分頁顯示記錄,使用同步連接配接。
<b>教學内容:</b>
5.1 資料源 5.2 jdbc-odbc 橋接器
5.3 查詢記錄 5.4 更新記錄
5.5 添加記錄 5.6 删除記錄
5.7 分頁顯示記錄 5.8 連接配接資料庫的其他方式
5.9 查詢 excel 電子表格 5.10 使用同步連接配接
<b>教學基本要求:</b>
了解:資料源的設定
了解:jdbc-odbc 橋接器,連接配接資料庫的其他方式,查詢 excel 電子表格
掌握:查詢記錄,更新記錄,添加記錄,删除記錄
應用:分頁顯示記錄,使用同步連接配接<b> </b>
<b>教學重點教學難點:</b>
jdbc-odbc 橋接器,查詢記錄,更新記錄,添加記錄,删除記錄,分頁顯示記錄,使用同步連接配接
<b>教學方法:</b>
<b>教學手段:</b>多媒體教學和計算機程式示範<b> </b>
<b>教學小結:</b><b> </b><b>(見教學程序)</b>
<b>作業與思考:</b>見課後習題<b> </b>
<b>課後記載:</b>
<b> </b>
<b></b>
<b>教</b><b> </b><b>學</b><b> </b><b>進</b><b> </b><b>程</b><b> </b>
<b>第5章 jsp中使用資料庫</b>
在jsp中可以使用java的jdbc技術,實作對資料庫中表記錄的查詢、修改和删除等操作。jdbc技術在jsp開發中占有很重要的地位。
jdbc(java database connectivity)是java資料庫連接配接api。簡單地說,jdbc能完成三件事:
(1) 與一個資料庫建立連接配接,
(2) 向資料庫發送sql語句,
(3) 處理資料庫傳回的結果。
jdbc在設計上和odbc很相似。jdbc和資料庫建立連接配接的一種常見方式是建立起一個jdbc─odbc橋接器。由于odbc驅動程式被廣泛的使用,建立這種橋接器後,使得jdbc有能力通路幾乎所有類型的資料庫。jdbc也可以直接加載資料庫驅動程式通路資料庫,我們将在2.8節讨論。
如果使用jdbc─odbc橋接器通路資料庫,事先必須設定資料源。
<b>5.1 </b><b>資料源</b>
假設要通路sql server伺服器上的pubs資料庫,該庫有一個表students,如圖5.1、5.2所示。
為連接配接一個sql-server資料庫,我們需設定一個資料源。在控制台選擇odbc資料源,如圖5.3所示。
輕按兩下odbc資料源圖示。出現如圖5.4所示界面,圖5.4中顯示了使用者已有的資料源的名稱。
選擇“使用者dsn”,點選add按鈕,增加新的資料源。如圖5.5所示:
為新增的資料源選擇驅動程式,因為要通路sql server資料庫,選擇sql server,點選完成按鈕(為資料源選擇了驅動程式),出現設定資料源具體項目的對話框,如圖5.6所示。在名稱欄裡為資料源起一個你自己喜歡的名字,這裡我們起的名字是sun(當然,如果你喜歡的話,可以把名字叫做moon.)。這個資料源就是指某個資料庫(将來随着計算機的進步,我們也可能有能力把資料源設成是一個衛星上來的信号)。在“你想連接配接哪個sql server?”欄中選擇或輸入一個資料庫伺服器,這裡我們選擇了網絡上的另一台機器:ping。
單擊“下一步”出現圖5.7畫面,選擇連接配接sql server 的id。
在圖5.7的對話框中,選擇“使用使用者輸入登入辨別号和密碼的sql server驗證”選項,在這裡我們選擇使用者名為sa (不需要密碼),單擊“下一步”出現如圖5.8所示的選擇資料庫的對話框。
選中“改變預設的資料庫為”複選框,在下拉菜單裡,我們選擇使用者sa有權限操作的資料庫pubs。單擊“下一步”出現完成資料源設定的對話框如圖5.9。
在圖5.9中,單擊“完成”出現你所配置的資料源的資訊視窗,如圖5.10所示。
點選“測試資料源”按鈕,如果正常就會出現資料源設定成功的視窗,如圖5.11所示。
<b>5.2 jdbc-odbc</b><b>橋接器</b>
現在你可以這樣的直覺了解:我們有了一個資料源,這個資料源就是一個資料庫。為了要連接配接到這個資料庫,需要建立一個jdbc─odbc橋接器,即加載橋接器驅動程式。
class.forname("sun.jdbc.odbc.jdbcodbcdriver");
這裡,class是包java.lang中的一個類,該類通過調用它的靜态方法forname就可以建立jdbc-odbc橋接器。建立橋接器時可能發生異常,是以建立橋接器的标準是:
try { class.forname("sun.jdbc.odbc.jdbcodbcdriver");
}
catch(classnotfoundexception e)
{}
<b>5.3 </b><b>查詢記錄</b>
要查詢資料庫中的記錄,必須和資料庫建立連接配接,由于使用的是jdbc-odbc方式通路資料庫,那麼就要與資料源建立連接配接。
(1)連接配接到資料庫
首先使用包java.sql中的connection類聲明一個對象,然後再使用類drivermanager調用它的靜态方法getconnection建立這個連接配接對象:
connection con = drivermanager.getconnection("jdbc:odbc:資料源名字","login name", "password ");
假如您沒有為資料源設定login name 和password,那麼連接配接形式是:
connection con = drivermanager. getconnection("jdbc:odbc:資料源名字", "", "");
與資料庫pubs(它就是資料源sun)建立連接配接,格式如下:
try{ connection con = drivermanager. getconnection("jdbc:odbc:sun", "sa", "");
}
catch(sqlexception e)
{}
這樣就建立了到資料庫pubs的連接配接。
(2)向資料庫發送sql語句。
首先使用statement聲明一個sql語句對象,然後通過剛才建立的連接配接資料庫的對象con調用方法createstatment()建立這個sql語句對象。
try {statement sql=con.createstatement();}
catch(sqlexception e ){}
(3)處理查詢結果
有了sql語句對象後,這個對象就可以調用相應的方法實作對資料庫中表的查詢和修改。并将查詢結果存放在一個resultset類聲明的對象中,也就是說sql語句對資料庫的查詢操作将傳回一個resultset對象:
resultset rs=sql.executequery("select * from 成績表");
resultset對象是以統一形式的列組織的資料行組成。resultset對象一次隻能看到一個資料行,使用next()方法走到下一資料行,獲得一行資料後,resultset對象可以使用getxxxx方法獲得字段值,将位置索引(第一列使用1,第二列使用2等等)或字段名傳遞給getxxxx方法的參數即可。
resultset類的若幹方法
l boolean next()
l byte getbyte(int columnindex)
l date getdate(int columnindex)
l double getdouble(int columnindex)
l float getfloat(int columnindex)
l int getint(int columnindex)
l long getlong(int columnindex)
l string getstring(int columnindex)
l byte getbyte(string columnname)
l date getdate(string columnname)
l double getdouble(string columnname)
l float getfloat(string columnname)
l int getint(string columnname)
l long getlong(string columnname)
l string getstring(string columnname)
<b>5.3.1 </b><b>順序查詢</b>
使用結果集result的next()方法,可以順序的查詢。一個結果集将遊标最初定位在第一行的前面,第一次調用next()方法使遊标移動到第一行。next()方法傳回一個boolean型資料,當遊标移動到最後一行之後傳回false。
在下面的例子1中,我們查詢資料庫pubs(資料源sun)中students表裡的包含全部字段的記錄。
<b>例子</b><b>1</b>(效果如圖5.12所示)
example5_1.jsp:
<%@ page contenttype="text/html;charset=gb2312" %>
<%@ page import="java.sql.*" %>
<html>
<body>
<% connection con;
statement sql;
resultset rs;
try{class.forname("sun.jdbc.odbc.jdbcodbcdriver");
}
catch(classnotfoundexception e){}
try { con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
sql=con.createstatement();
rs=sql.executequery("select * from students");%>
<table border>
<tr>
<th width=100>學号
<th width=100姓名
<th width=50>數學成績
<th width=50>英語成績
<th width=50>實體成績
</tr>
<% while(rs.next())
{ out.print("<tr>");
out.print("<td >"+rs.getstring(1)+"</td>");
out.print("<td >"+rs.getstring(2)+"</td>");
out.print("<td >"+rs.getint("數學成績")+"</td>");
out.print("<td >"+rs.getint("英語成績")+"</td>");
out.print("<td >"+rs.getint("實體成績")+"</td>");
out.print("</tr>") ;
}
out.print("</table>");
con.close();
catch(sqlexception e1) {}
%>
</body>
</html>
在下面的例子2中查詢“英語成績”字段值大于80的記錄,但隻顯示“姓名”字段(第2個字段)和“英語成績”字段。
<b>例子</b><b>2</b>(效果如圖5.13所示)
example5_2.jsp:
try { con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
rs=sql.executequery("select * from students where 英語成績 >= 80 ");
out.print("<table border>");
out.print("<tr>");
out.print("<th width=100>"+"姓名");
out.print("<th width=50>"+"英語成績");
out.print("</tr>");
while(rs.next())
out.print("<td >"+rs.getstring(2)+"</td>");
out.print("</tr>") ;
<b>5.3.2 </b><b>遊動查詢</b>
前面我們學習了使用result的next()方法順序地查詢資料,但有時候我們需要在結果集中前後移動、或顯示結果集指定的一條記錄等等。這時,我們必須要傳回一個可滾動的結果集。為了得到一個可滾動的結果集,和上一節不同的是,我們必須使用下述方法先獲得一個statement對象:
statement stmt=con.createstatement(resultset.type_forword_only ,int concurrency);
然後,根據參數的type、concurrency的取值情況,stmt傳回相應類型的結果集:
resultset re=stmt.executequery(sql語句);
type的取值決定滾動方式,取值可以是:
l resultset.type_forword_only :結果集的遊标隻能向下滾動。
l resultset.type_scroll_insensitive :結果集的遊标可以上下移動,當資料庫變化時,目前結果集不變。
l resultset.type_scroll_sensitive :傳回可滾動的結果集,當資料庫變化時,目前結果集同步改變。
concurrency 取值決定是否可以用結果集更新資料庫,concurrency取值:
l resultset.concur_read_only:不能用結果集更新資料庫中的表。
l resultset.concur_updatetable:能用結果集更新資料庫中的表。
滾動查詢經常用到resultset的下述方法:
l public boolean previous():将遊标向上移動,該方法傳回boolean型資料,當移到結果集第一行之前時傳回false.
l public void beforefirst:将遊标移動到結果集的初始位置,即在第一行之前。
l public void afterlast():将遊标移到結果集最後一行之後。
l public void first():将遊标移到結果集的第一行。
l public void last():将遊标移到結果集的最後一行。
l public boolean isafterlast():判斷遊标是否在最後一行之後。
l public boolean isbeforefirst():判斷遊标是否在第一行之前
l public boolean iffirst():判斷遊标是否指向結果集的第一行。
l public boolean islast():判斷遊标是否指向結果集的最後一行。
l public int getrow():得到目前遊标所指行的行号,行号從1開始,如果結果集沒有行,傳回0
l public boolean absolute(int row):将遊标移到參數row指定的行号。
注意,如果row取負值,就是倒數的行數,absolute(-1)表示移到最後一行,absolute(-2)表示移到倒數第2行。當移動到第一行前面或最後一行的後面時,該方法傳回false。
在下面的例子中,首先将遊标移動到最後一行,然後再擷取行号,這樣就獲得表中的記錄數目。然後我們倒序輸出結果集中的記錄,即首先輸出最後一行。最後單獨輸出第5條記錄。
<b>例子3</b>(效果如圖5.14所示)
example5_3.jsp:
<% string name,number;
int math,physics,english;
connection con;
try{ con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
sql=
con.createstatement(resultset.type_scroll_sensitive,resultset.concur_read_only);
//傳回可滾動的結果集:
rs=sql.executequery("select * from students");
//将遊标移動到最後一行:
rs.last();
//擷取最後一行的行号:
int lownumber=rs.getrow();
out.print("該表共有"+lownumber+"條記錄");
out.print("<br>現在逆序輸出記錄:");
out.print("<table border>");
out.print("<th width=100>"+"學号");
out.print("<th width=50>"+"數學成績");
out.print("<th width=50>"+"實體成績");
out.print("</tr>");
//為了逆序輸出記錄,需将遊标移動到最後一行之後:
rs.afterlast();
while(rs.previous())
{ out.print("<tr>");
number=rs.getstring(1);
out.print("<td >"+number+"</td>");
name=rs.getstring(2);
out.print("<td >"+name+"</td>");
math=rs.getint("數學成績");
out.print("<td >"+math+"</td>");
english=rs.getint("英語成績");
out.print("<td >"+english+"</td>");
physics=rs.getint("實體成績");
out.print("<td >"+physics+"</td>");
out.print("</tr>") ;
}
out.print("</table>");
out.print("單獨輸出第5條記錄<br>");
rs.absolute(5);
number=rs.getstring(1);
out.print(number+",");
out.print(name+",");
out.print(math+",");
out.print(english+",");
out.print(physics+"。");
<b>5.3.3 </b><b>随機查詢</b>
在下面的例子中,我們随機從結果集中取出4條記錄,并計算4條記錄的數學成績的平均值。用math類的靜态方法random()可以産生一個大于0小于1的随機數,再用下述公式:
int i=(int)(math.random()*number+1);
産生一個1到number之間的随機數,根據這個随機數将遊标移動到相應的行,并輸出該行,算法的進一步細節可見下述例子4。
<b>例子</b><b>4</b>(效果如圖5.15所示)
example5_4.jsp:
<% string xuehao,name;
int math;
out.print("<th width=100>"+"學号");
out.print("<th width=100>"+"姓名");
out.print("<th width=50>"+"數學成績");
//擷取記錄數:
int number=lownumber;
double sum=0;
int 抽取數目=4;
int old_i[]={0,0,0,0};
int k=抽取數目;
int j=0;
while(抽取數目>0)
{int i=(int)(math.random()*number+1);//随機擷取一個1到number之間的數。
boolean boo=false;
for(int m=0;m<old_i.length;m++) //查找該行是否已被取出。
{if(i==old_i[m])
boo=true;
}
if(boo) continue; //假如該行已被取出,結束本次循環,繼續産生随機數。
rs.absolute(i); //遊标移到這一行。
out.print("<tr>");
xuehao=rs.getstring(1); //擷取該行學号字段的值。
out.print("<td >"+xuehao+"</td>");
name=rs.getstring(2); //擷取該行姓名字段的值。
out.print("<td >"+name+"</td>");
math=rs.getint("數學成績"); //擷取改行數學成績字段的值。
out.print("<td >"+math+"</td>");
out.print("</tr>") ;
sum=sum+math;
抽取數目--;
old_i[j]=i; //記錄已取出的行号。
j++;
}
out.print("</table>");
out.print("平均成績是:"+sum/k);
con.close();
<b>5.3.4 </b><b>參數查詢</b>
在下面的例子中,客戶通過example5_5.jsp頁面輸入查詢條件,如按姓名查詢成績或按分數段查詢學生成績等等。輸入姓名送出給byname.jsp頁面,輸入分數段送出給byscore.jsp頁面。
<b>例子5</b>(效果如圖5.16、5.17、5.18所示)
example5_5.jsp:
<font size=1>
<form action="byname.jsp" method="post">
<p>成績查詢
<p>輸入姓名:
<input type=text name="name">
<input type=submit name="g" value="送出">
</form>
<form action="byscore.jsp" method="post" >
<p>根據分數查詢名單:<br> 英語分數在
<input type=text name="englishmin" value=0>
和
<input type=text name="englishmax" value=100>
之間
<br> 數學分數在
<input type=text name="mathmin" value=0>
<input type=text name="mathmax" value=100>
<br> <input type=submit value="送出">
bynename.jsp:
<% //擷取送出的姓名:
string name=request.getparameter("name");
if(name==null)
{name="";
}
byte b[]=name.getbytes("iso-8859-1");
name=new string(b);
connection con=null;
statement sql=null;
resultset rs=null;
try{class.forname("sun.jdbc.odbc.jdbcodbcdriver");
}
catch(classnotfoundexception e){}
try { con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
sql=con.createstatement();
string condition="select * from students where 姓名 = "+"'"+name+"'";
rs=sql.executequery(condition);
out.print("<tr>");
out.print("<th width=100>"+"學号");
out.print("<th width=100>"+"姓名");
out.print("<th width=50>"+"數學成績");
out.print("<th width=50>"+"英語成績");
out.print("<th width=50>"+"實體成績");
out.print("</tr>");
while(rs.next())
{ out.print("<tr>");
out.print("<td >"+rs.getstring(1)+"</td>");
out.print("<td >"+rs.getstring(2)+"</td>");
out.print("<td >"+rs.getint("數學成績")+"</td>");
out.print("<td >"+rs.getint("英語成績")+"</td>");
out.print("<td >"+rs.getint("實體成績")+"</td>");
out.print("</tr>") ;
}
out.print("</table>");
con.close();
}
catch(sqlexception e)
{ }
%>
byscore.jsp:
<% //擷取送出的分數的最大值和最小值:
string englishmax=request.getparameter("englishmax");
if(englishmax==null)
{englishmax="100";
string englishmin=request.getparameter("englishmin");
if(englishmin==null)
{englishmin="0";
string mathmax=request.getparameter("mathmax");
if(mathmax==null)
{mathmax="100";
}
string mathmin=request.getparameter("mathmin");
if(mathmin==null)
{mathmin="0";
try
{ con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
sql=con.createstatement();
string econdition="英語成績 <= "+englishmax+" and "+"英語成績 >= "+englishmin;
string mcondition="數學成績 <= "+mathmax+" and "+"數學成績 >= "+mathmin;
string condition="select * from students where "+mcondition+" and "+econdition;
rs=sql.executequery(condition);
out.print("<table border>");
out.print("<tr>");
out.print("<th width=50>"+"實體成績");
out.print("</tr>");
{ out.print("<tr>");
out.print("</tr>") ;
con.close();
catch(sqlexception e)
{}
<b>5.3.5 </b><b>排序查詢</b>
可以在sql語句中使用order by子語句,對記錄排序。在下面的例子中,使用sql語句的order by子語句查詢所同學的成績,可以選擇按3科的總分從低到高排列記錄、按姓氏拼音排序或英語成績排序。
例如,按總成績排序查詢的sql語句:
select * from student order by 數學成績+英語成績+實體成績。
<b>例子6</b>(效果如圖5.19、5.20所示)
example5_6:
<p>查詢成績:
<form action="byname1.jsp" method=post name=form>
<input type="radio" name="r" value="姓名">按姓氏排序
<input type="radio" name="r" value="數學成績+英語成績+實體成績">按總分排序
<input type="radio" name="r" value="英語成績">按英語排序
<br> <input type=submit name="g" value="送出">
byname1.jsp:
<% //擷取送出的排序方式:
string name=request.getparameter("r");
{name="";}
string number,xingming;
int math,english,physics;
try { con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
string condition="select * from students order by "+name;
rs=sql.executequery(condition);
out.print("<tr>");
out.print("<th width=50>"+"總成績");
while(rs.next())
{ out.print("<tr>");
number=rs.getstring(1);
out.print("<td >"+number+"</td>");
xingming=rs.getstring(2);
out.print("<td >"+xingming+"</td>");
math=rs.getint("數學成績");
out.print("<td >"+math+"</td>");
english=rs.getint("英語成績");
out.print("<td >"+english+"</td>");
physics=rs.getint("實體成績");
out.print("<td >"+physics+"</td>");
int total=math+english+physics;
out.print("<th >"+total+"</th>");
out.print("</tr>") ;
}
{ }
<b>5.3.6 </b><b>分析結果集查詢</b>
通過分析結果集來輸出記錄。在下面的例子中查詢所有姓王的同學的成績,首先判斷結果集中,姓氏字段的值是否是某個姓氏,然後輸出全部該姓氏的同學的成績。
<b>例子7</b>(效果如圖5.21所示)
example5_7.jsp:
<p>輸入學生的姓氏:
<br> <form action="byname2.jsp" method=post name=form>
<input type="text" name="name" value="王">
byname2.jsp:
<% //擷取送出的姓氏:
try{ con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
string condition="select * from students" ;
{ number=rs.getstring(1);
xingming=rs.getstring(2);
if(xingming.startswith("王"))
{ out.print("<tr>");
out.print("<td >"+number+"</td>");
out.print("<td >"+xingming+"</td>");
math=rs.getint("數學成績");
english=rs.getint("英語成績");
out.print("<td >"+english+"</td>");
physics=rs.getint("實體成績");
out.print("<td >"+physics+"</td>");
out.print("</tr>") ;
}
{ }
<b>5.3.7 </b><b>使用統配符查詢</b>
可以用sql語句操作符like進行模式般配,使用“%”代替一個或多個字元,用一個下劃線“_”代替一個字元。比如,下述語句查詢姓氏是“王”的記錄:
rs=sql.executequery("select * from students where 姓名 like '王%' ");
請将上面的例子7改為通配符查詢,查詢所有姓氏是王的記錄。
<b>5.4 </b><b>更新記錄</b>
我們可以使用sql語句更新記錄中字段的值
statement對象調用方法:
public int executeupdate(string sqlstatement);
通過參數sqlstatement指定的方式實作對資料庫表中記錄的字段值的更新,例如,下述語句将表students中王名同學的數學字段的值更新88:
executeupdate("update students set 數學成績 = 88 where 姓名='王名'");
注:你可以使用一個statement對象進行更新和查詢操作,但需要注意的是,當查詢語句傳回結果集後,沒有立即輸出結果集的記錄,而接着執行了更新語句,那麼結果集就不能輸出記錄了。要想輸出記錄就必須重新傳回結果集。
在下面的例子8中,可以更新學生的各科的成績。在example5_8.jsp頁面送出學生的姓名以及這個學生新的成績到newresult.jsp頁面,該頁面負責更新記錄的字段值。
<b>例子8</b>(效果如圖5.22、5.23所示)
example5_8.jsp:
<body bgcolor=pink >
<form action="newresult.jsp" method=post>
輸入要修改成績的同學的姓名:<br>
<input type="text" name="name">
<br>輸入新的數學成績:
<input type="text" name="math">
<br>輸入新的英語成績:
<input type="text" name="english">
<br>輸入新的實體成績:
<input type="text" name="physics">
<br><input type="submit" name="b" value="送出更新">
<p>資料庫更新前的資料記錄是:
out.print("<th width=100>"+"姓名");
</font>
newresult.jsp:
<body bgcolor=pink ><font size=1>
<% //擷取送出的姓名:
//擷取送出的新的數學成績:
string newmath=request.getparameter("math");
if(newmath==null)
{newmath="-100";
//擷取送出的新的英語成績:
string newenglish=request.getparameter("english");
if(newenglish==null)
{newenglish="-100";
//擷取送出的新的實體成績:
string newphysics=request.getparameter("physics");
if(newphysics==null)
{newphysics="-100";
try {con=drivermanager.getconnection("jdbc:odbc:sun","sa","");
sql=con.createstatement();
string condition1=
"update students set 數學成績 = "+newmath+" where 姓名="+"'"+name+"'" ,
condition2=
"update students set 英語成績 = "+newenglish+" where 姓名="+"'"+name+"'" ,
condition3=
"update students set 實體成績 = "+newphysics+" where 姓名="+"'"+name+"'" ;
//執行更新操作:
sql.executeupdate(condition1);
sql.executeupdate(condition2);
sql.executeupdate(condition3);
//顯示更新後的表中的記錄:
%>
<p>更新後的表的記錄:
<%
rs=sql.executequery("select * from students");
{
out.print("<tr>");
number=rs.getstring(1);
xingming=rs.getstring(2);
math=rs.getint("數學成績");
out.print("<td >"+english+"</td>");
out.print("</tr>") ;
{ }
<b>5.5 </b><b>添加記錄</b>
我們可以使用sql語句添加新的記錄,statement對象調用方法:
通過參數sqlstatement指定的方式實作向資料庫表中添加新記錄,例如,下述語句将向表students中添加一條新的記錄:(’199911’,’美麗家’,100,99,98)。
executeupdate("insert into students values (’199911’,’美麗家’,100,99,98)");
在下面的例子9中,可以添加新的記錄。在example5_9.jsp頁面送出新的記錄到newdatabase.jsp頁面,該頁面負責添加新的記錄。
注:你可以使用一個statement對象進行添加和查詢操作,但需要注意的是,當查詢語句傳回結果集後,沒有立即輸出結果集的記錄,而接着執行了添加語句,那麼結果集就不能輸出記錄了。要想輸出記錄就必須重新傳回結果集。
<b>例子9</b>(效果如圖5.24、5.25所示)
example5_9.jsp:
<p>添加新的記錄到資料庫:
<form action="newdatabase.jsp" method=post>
同學學号:
<input type="text" name="number">
<br>同學姓名:
<br>數學成績:
<br>英語成績:
<br>實體成績:
<br><input type="submit" name="b" value="送出添加">
<p>資料庫添加記錄前的資料記錄是:
try { con=drivermanager.getconnection("jdbc:odbc:moon","sa","");
sql=con.createstatement();
newdatabase.jsp:
<% //擷取送出的學号:
string number=request.getparameter("number");
if(number==null)
{number="";
byte b[]=number.getbytes("iso-8859-1");
number=new string(b);
//擷取送出的姓名:
byte c[]=name.getbytes("iso-8859-1");
name=new string(c);
string m=request.getparameter("math");
if(m==null)
{m="-100"; }
string e=request.getparameter("english");
if(e==null)
{e="-100"; }
string p=request.getparameter("physics");
if(p==null)
{p="-100"; }
try{class.forname("sun.jdbc.odbc.jdbcodbcdriver"); }
catch(classnotfoundexception event){}
try {con=drivermanager.getconnection("jdbc:odbc:moon","sa","");
string condition=
"insert into students values"+"("+"'"+number+"','"+name+"',"+m+","+e+","+p+")";
sql.executeupdate(condition); //執行添加操作:
//顯示添加新記錄後表中的記錄:
<p>添加新記錄後的表:
rs=sql.executequery("select * from students order by 學号 ");
{ out.print("<tr>");
string n=rs.getstring(1);
out.print("<td >"+n+"</td>");
string xingming=rs.getstring(2);
int math=rs.getint("數學成績");
int english=rs.getint("英語成績");
int physics=rs.getint("實體成績");
catch(sqlexception event)
<b>5.6 </b><b>删除記錄</b>
我們可以使用sql語句删除記錄,statement對象調用方法:
通過參數sqlstatement指定的方式删除資料庫表中的記錄,例如,下述語句将删除學号是199904的記錄:
executeupdate("delete from students where 學号 = ‘199904’ ");
在下面的例子10中,可以删除已有的記錄。在example5_10.jsp頁面送出要被删除的記錄的字段值到delete.jsp頁面,delete.jsp頁面負責删除相應的記錄。
注:你可以使用一個statement對象進行删除和查詢操作,但需要注意的是,當查詢語句傳回結果集後,沒有立即輸出結果集的記錄,而接着執行了删除語句,那麼結果集就不能輸出記錄了。要想輸出記錄就必須重新傳回結果集。
<b>例子10</b>(效果如圖5.26、5.27所示)
example5_10.jsp:
<p>删除記錄:
<form action="delete.jsp" method=post>
輸入被删除記錄的學号:
<br>
<br><input type="submit" name="b" value="送出删除">
<p>資料庫删除前的資料記錄是:
delete.jsp:
//删除操作:
string deleteall="delete from students where 學号"+" = "+"'"+number+"'";
sql.executeupdate(deleteall);
%>
<p>删除記錄後的表:
out.print("<td >"+xingming+"</td>");
int physics=rs.getint("實體成績");
{out.print(""+event);
<b>5.7 </b><b>分頁顯示記錄</b>
我們簡單地實作資料庫表中記錄的分頁顯示。
假設總記錄數為m,每頁顯示數量是n,那麼總頁數的計算公式是:
(1) 如果m除以n的餘數大于0,總頁數等于m除以n的商加1;
(2) 如果m除以n的餘數等于0,總頁數等于m除以n的商。
即
總頁數=(m%n)==0?(m/n):(m/n+1);
如果準備顯示第p頁的内容,應當把遊标移動到第(p-1)*n+1條記錄處。
showbypage.jsp:(效果如圖5.28所示)
<%! int pagesize=3; //每頁顯示的記錄數。
int pagecount=0; //分頁後的總頁數。
<%-- 客戶通過表單送出欲要顯示的頁碼數--%>
<form action="" method=get >
輸入頁碼數<input type=text name=showpage size=4 >
<input type=submit name=g value=送出>
</form>
<% connection con;
int lastrow=rs.getrow();
//計算分頁後的總頁數:
pagecount=(lastrow%pagesize==0)?(lastrow/pagesize):(lastrow/pagesize+1);
//目前顯示的初始頁數:
int showpage=1;
//告知客戶總頁數:
<p> 共有<%=pagecount%>頁
<br>每頁顯示<%=pagesize%>條記錄.
<% //擷取客戶想要顯示的頁數:
string integer=request.getparameter("showpage");
if(integer==null)
{ integer="1";
}
try {showpage=integer.parseint(integer);
catch(numberformatexception e)
{showpage=1;
if(showpage<=1)
{showpage=1;
}
if(showpage>=pagecount)
{showpage=pagecount;
}
<br>目前顯示第<%=showpage%>頁
<% //如果要顯示第showpage頁,那麼遊标應移到posion的值是:
int posion=(showpage-1)*pagesize+1;
rs.absolute(posion); // 設定遊标的位置
out.print("<table border>");
out.print("<tr>");
out.print("</tr>");
for (int i=1;i<=pagesize;i++)
out.print("<td >"+rs.getint("實體成績")+"</td>");
rs.next();
<b>5.8 </b><b>連接配接資料庫的其它方式</b>
<b>5.8.1 </b><b>連接配接oracle資料庫</b>
我們也可以通過jdbc-odbc橋接器和oracle資料庫建立連接配接,但這種連接配接的品質依賴于odbc。下面介紹通過直接加載oracle資料庫驅動程式來連接配接資料庫的方法。
安裝oracle後,找到目錄:oracle/ora81/jdbc中的檔案:classes12.zip;将該檔案拷貝到你的jdk的如下目錄中:
f:/jdk1.3/jre/lib/ext
并将classes.zip重新命名為classes.jre或classes.jar。
通過如下的兩個步驟和一個oracle資料庫建立連接配接:
(1)加載驅動程式:
class.forname("oracle.jdbc.driver.oracledriver");
(2)建立連接配接:
connection conn=
drivermanager.getconnection( “jdbc:oracle:thin:@主機host:端口号:資料庫名”, “使用者名”, “密碼”);
<b>例子</b><b>11</b>(效果如圖5.29所示)
example5_11.jsp:
<% connection con=null;
try{class.forname("oracle.jdbc.driver.oracledriver");
try
{ con=
drivermanager.getconnection("jdbc:oracle:thin:@192.168.0.35:1521:lea","scott","tiger");
rs=sql.executequery("select * from emp");
out.print("<th width=100>"+"empno");
out.print("<th width=50>"+"ename");
int n=rs.getint(1);
out.print("<td >"+n+"</td>");
string e=rs.getstring(2);
out.print("<td >"+e+"</td>");
out.print("</tr>") ;
catch(sqlexception e1) {out.print(""+e1);}
注:如果出現無法找到oracledriver異常,請首先檢查jdk的目錄:jdk/jre/lib/ext中是否有classes12.jre檔案,如果有該檔案,仍出現oracledriver異常,嘗試将下列路徑加入環境變量
jdk/jre/lib/ext/classes.jre
<b>5.8.2 </b><b>連接配接mysql資料庫</b>
可以到位址:http://www.wordsercer.com/mm.mysql下載下傳驅動程式,然後安裝到某個盤,比如c:。
将下列路徑加入環境變量
c:/mm.mysql.jdbc-2.0pre5。
與一個mysal資料庫建立連接配接有如下2步:
class.forname("org.gjt.mm.mysql.driver").newinstance();
connection conn=drivermanager.getconnection(”jdbc:mysql://host:port:資料庫名”,”使用者名”,”密碼”);
<b>5.9 </b><b>查詢excel電子表格</b>
有時需要查詢excel或更新删除excel電子表格的内容,可以通過jdbc-odbc橋接器通路excel表格。通路exel表格和我們通路其它的資料庫有所不同,結合例子講述如下:
假設有電子表格:goods.xls,見下圖5.30。
(1) 設定資料源:
設定資料源的名字是star,為資料源選擇的驅動程式是:microsoft excel driver
(2) 選擇表:
與通路其它資料庫不同的是,我們必須在電子表格中選出一工作區作為連接配接時使用的表。
在excel電子表格中拖動滑鼠選出範圍,如下圖5.31所示。然後在excel菜單中選擇插入→名稱→定義,給選中的工作區命名(這一工作區的名稱将作為連接配接時使用的表名)。如圖5.32所示。
這樣我們就建立了一個名字是“品名”、有3個字段的表。現在就可以在jsp中查詢、更新、删除這個表中的記錄了。
下面的例子12查詢了“品名”表中的全部記錄。
<b>例子</b><b>12</b>(效果如圖5.33所示)
example5_12.jsp:
<% connection con;
statement sql;
resultset rs;
}
try { con=drivermanager.getconnection("jdbc:odbc:star","","");
rs=sql.executequery("select * from 品名 ");
out.print("<th width=100>"+"品名");
out.print("<th width=50>"+"機關");
out.print("<th width=50>"+"單價");
string name=rs.getstring(1);
string unit=rs.getstring(2);
out.print("<td >"+unit+"</td>");
string unitprice=rs.getstring(3);
out.print("<td >"+unitprice+"</td>");
<b>5.10 </b><b>使用同步連接配接</b>
資料庫操作中,建立連接配接是耗時最大的操作之一。如果客戶通路的是同一資料庫,那麼,為每個客戶都建立一個連接配接是不合理的。我們已經知道,在“<%!”和“%>”之間聲明的變量在整個jsp頁面内都有效,因為jsp引擎将jsp頁面轉譯成java檔案時,将這些變量作為類的成員變量。這些變量的記憶體空間直到伺服器關閉才釋放。當多個客戶請求一個jsp頁面時,jsp引擎為每個客戶啟動一個線程而不是啟動一個程序,這些線程由web伺服器程序來管理,它們共享jsp頁面的成員變量。在處理多線程問題時,可以将線程共享的變量放入一個synchronized塊,或将修改該變量的方法用synchronized來修飾,這樣,當一個客戶用synchronized塊或synchronized方法修改一個共享變量時,其它線程就必須等待,直到該線程執行完該方法或同步塊。這樣,我們可以把connection對象作為一個成員變量被所有的客戶共享,也就是說第一個通路資料庫的客戶負責建立連接配接,以後所有的客戶共享這個連接配接,每個客戶都不要關閉這個共享的連接配接。
<b>例子13</b>(效果如圖5.34、5.35所示)
example5_13.jsp:
<%! //聲明一個共享的連接配接對象:
%>
<% statement sql=null;
//第一個客戶負責建立連接配接對象:
if(con==null)
{ try{class.forname("sun.jdbc.odbc.jdbcodbcdriver");
catch(classnotfoundexception e)
{out.print(e);
try {con=drivermanager.getconnection("jdbc:odbc:moon","sa","");
rs =sql.executequery("select * from students");
out.print("i am first");
catch(sqlexception e)
{out.print(e);
else //其它客戶通過同步塊使用這個連接配接:
{ synchronized(con)
{ try { sql=con.createstatement();
rs =sql.executequery("select * from students");
out.print("i am not first");
catch(sqlexception e)
{out.print(e);
{ out.print("<table border>");
string number=rs.getstring(1);
string name=rs.getstring(2);
int math=rs.getint("數學成績");
int english=rs.getint("英語成績");
out.print("<td >"+english+"</td>");
int physics=rs.getint("實體成績");
out.print("</tr>") ;
out.print("</table>");
}