天天看點

JSP 五講

<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:

&lt;%@ page contenttype="text/html;charset=gb2312" %&gt;

&lt;%@ page import="java.sql.*" %&gt;

&lt;html&gt;

&lt;body&gt;

 &lt;% 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");%&gt;

        &lt;table border&gt;

        &lt;tr&gt;

            &lt;th width=100&gt;學号

            &lt;th width=100姓名

            &lt;th width=50&gt;數學成績

           &lt;th width=50&gt;英語成績

            &lt;th width=50&gt;實體成績

         &lt;/tr&gt;

      &lt;% while(rs.next())

       { out.print("&lt;tr&gt;");

             out.print("&lt;td &gt;"+rs.getstring(1)+"&lt;/td&gt;");

             out.print("&lt;td &gt;"+rs.getstring(2)+"&lt;/td&gt;");

             out.print("&lt;td &gt;"+rs.getint("數學成績")+"&lt;/td&gt;");

             out.print("&lt;td &gt;"+rs.getint("英語成績")+"&lt;/td&gt;");

             out.print("&lt;td &gt;"+rs.getint("實體成績")+"&lt;/td&gt;");  

        out.print("&lt;/tr&gt;") ;

        }

        out.print("&lt;/table&gt;");

        con.close();

   catch(sqlexception e1) {}

 %&gt;

&lt;/body&gt;

&lt;/html&gt;

在下面的例子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 英語成績 &gt;= 80 ");

         out.print("&lt;table border&gt;");

         out.print("&lt;tr&gt;");

            out.print("&lt;th width=100&gt;"+"姓名");

            out.print("&lt;th width=50&gt;"+"英語成績");

         out.print("&lt;/tr&gt;");

       while(rs.next())

             out.print("&lt;td &gt;"+rs.getstring(2)+"&lt;/td&gt;");

         out.print("&lt;/tr&gt;") ;

<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:

 &lt;% 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("&lt;br&gt;現在逆序輸出記錄:");

         out.print("&lt;table border&gt;");

            out.print("&lt;th width=100&gt;"+"學号");

            out.print("&lt;th width=50&gt;"+"數學成績");

            out.print("&lt;th width=50&gt;"+"實體成績");

       out.print("&lt;/tr&gt;");

       //為了逆序輸出記錄,需将遊标移動到最後一行之後:

        rs.afterlast();

        while(rs.previous())

        { out.print("&lt;tr&gt;");

             number=rs.getstring(1);

             out.print("&lt;td &gt;"+number+"&lt;/td&gt;");

             name=rs.getstring(2);

             out.print("&lt;td &gt;"+name+"&lt;/td&gt;");

             math=rs.getint("數學成績");

             out.print("&lt;td &gt;"+math+"&lt;/td&gt;");

             english=rs.getint("英語成績");

             out.print("&lt;td &gt;"+english+"&lt;/td&gt;");

             physics=rs.getint("實體成績");

             out.print("&lt;td &gt;"+physics+"&lt;/td&gt;");  

         out.print("&lt;/tr&gt;") ;         

         }

       out.print("&lt;/table&gt;");

       out.print("單獨輸出第5條記錄&lt;br&gt;");

        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:

 &lt;% string xuehao,name;

    int math;

             out.print("&lt;th width=100&gt;"+"學号");

             out.print("&lt;th width=100&gt;"+"姓名");

             out.print("&lt;th width=50&gt;"+"數學成績");

        //擷取記錄數:

        int number=lownumber;

        double sum=0;

        int 抽取數目=4;

        int old_i[]={0,0,0,0};

        int k=抽取數目;

        int j=0;

           while(抽取數目&gt;0)

                {int i=(int)(math.random()*number+1);//随機擷取一個1到number之間的數。

                 boolean boo=false;

                 for(int m=0;m&lt;old_i.length;m++)   //查找該行是否已被取出。

                      {if(i==old_i[m])

                       boo=true;

                      }

                 if(boo)  continue;   //假如該行已被取出,結束本次循環,繼續産生随機數。

                 rs.absolute(i);                   //遊标移到這一行。

                 out.print("&lt;tr&gt;");

                 xuehao=rs.getstring(1);           //擷取該行學号字段的值。

                 out.print("&lt;td &gt;"+xuehao+"&lt;/td&gt;");

                 name=rs.getstring(2);              //擷取該行姓名字段的值。

                 out.print("&lt;td &gt;"+name+"&lt;/td&gt;");

                 math=rs.getint("數學成績");        //擷取改行數學成績字段的值。

                 out.print("&lt;td &gt;"+math+"&lt;/td&gt;");

                 out.print("&lt;/tr&gt;") ;

                 sum=sum+math;

                 抽取數目--;

                 old_i[j]=i;        //記錄已取出的行号。

                 j++;     

                }

         out.print("&lt;/table&gt;");

         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:

&lt;font size=1&gt;

&lt;form action="byname.jsp" method="post"&gt;

 &lt;p&gt;成績查詢

 &lt;p&gt;輸入姓名:

  &lt;input type=text name="name"&gt;

  &lt;input type=submit name="g" value="送出"&gt;

&lt;/form&gt;

&lt;form action="byscore.jsp" method="post" &gt;

 &lt;p&gt;根據分數查詢名單:&lt;br&gt;  英語分數在

&lt;input type=text name="englishmin" value=0&gt;

  和

 &lt;input type=text name="englishmax" value=100&gt;

  之間

 &lt;br&gt; 數學分數在

&lt;input type=text name="mathmin" value=0&gt;

 &lt;input type=text name="mathmax" value=100&gt;

  &lt;br&gt;  &lt;input type=submit  value="送出"&gt;

bynename.jsp:

  &lt;% //擷取送出的姓名:

    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("&lt;tr&gt;");

              out.print("&lt;th width=100&gt;"+"學号");

              out.print("&lt;th width=100&gt;"+"姓名");

              out.print("&lt;th width=50&gt;"+"數學成績");

              out.print("&lt;th width=50&gt;"+"英語成績");

              out.print("&lt;th width=50&gt;"+"實體成績");

              out.print("&lt;/tr&gt;");

              while(rs.next())

                   { out.print("&lt;tr&gt;");

                     out.print("&lt;td &gt;"+rs.getstring(1)+"&lt;/td&gt;");

                     out.print("&lt;td &gt;"+rs.getstring(2)+"&lt;/td&gt;");

                     out.print("&lt;td &gt;"+rs.getint("數學成績")+"&lt;/td&gt;");

                     out.print("&lt;td &gt;"+rs.getint("英語成績")+"&lt;/td&gt;");

                     out.print("&lt;td &gt;"+rs.getint("實體成績")+"&lt;/td&gt;");  

                     out.print("&lt;/tr&gt;") ; 

                    }

              out.print("&lt;/table&gt;");

              con.close();

           }

    catch(sqlexception e)

           {  }

%&gt;

byscore.jsp:

  &lt;% //擷取送出的分數的最大值和最小值:

    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="英語成績 &lt;= "+englishmax+" and "+"英語成績 &gt;= "+englishmin;

           string mcondition="數學成績 &lt;= "+mathmax+" and "+"數學成績 &gt;= "+mathmin;

           string condition="select * from students where "+mcondition+" and "+econdition;

           rs=sql.executequery(condition);

       out.print("&lt;table border&gt;");

            out.print("&lt;tr&gt;");

            out.print("&lt;th width=50&gt;"+"實體成績");

            out.print("&lt;/tr&gt;");

           { out.print("&lt;tr&gt;");

             out.print("&lt;/tr&gt;") ;         

      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:

&lt;p&gt;查詢成績:

&lt;form action="byname1.jsp" method=post name=form&gt;

       &lt;input type="radio" name="r" value="姓名"&gt;按姓氏排序

       &lt;input type="radio" name="r" value="數學成績+英語成績+實體成績"&gt;按總分排序

       &lt;input type="radio" name="r" value="英語成績"&gt;按英語排序

&lt;br&gt;  &lt;input type=submit name="g" value="送出"&gt;

byname1.jsp:

  &lt;% //擷取送出的排序方式:

    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("&lt;tr&gt;");

            out.print("&lt;th width=50&gt;"+"總成績");

           while(rs.next())

             { out.print("&lt;tr&gt;");

               number=rs.getstring(1);

               out.print("&lt;td &gt;"+number+"&lt;/td&gt;");

               xingming=rs.getstring(2);

               out.print("&lt;td &gt;"+xingming+"&lt;/td&gt;");

               math=rs.getint("數學成績");

               out.print("&lt;td &gt;"+math+"&lt;/td&gt;");

               english=rs.getint("英語成績");

               out.print("&lt;td &gt;"+english+"&lt;/td&gt;");

               physics=rs.getint("實體成績");

               out.print("&lt;td &gt;"+physics+"&lt;/td&gt;");

               int total=math+english+physics;

               out.print("&lt;th &gt;"+total+"&lt;/th&gt;");

               out.print("&lt;/tr&gt;") ;

              }

       {  }

<b>5.3.6 </b><b>分析結果集查詢</b>

通過分析結果集來輸出記錄。在下面的例子中查詢所有姓王的同學的成績,首先判斷結果集中,姓氏字段的值是否是某個姓氏,然後輸出全部該姓氏的同學的成績。

<b>例子7</b>(效果如圖5.21所示)

example5_7.jsp:

&lt;p&gt;輸入學生的姓氏:

&lt;br&gt; &lt;form action="byname2.jsp" method=post name=form&gt;

       &lt;input type="text" name="name" value="王"&gt;

byname2.jsp:

  &lt;% //擷取送出的姓氏:

       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("&lt;tr&gt;");

                 out.print("&lt;td &gt;"+number+"&lt;/td&gt;");

                 out.print("&lt;td &gt;"+xingming+"&lt;/td&gt;");

                 math=rs.getint("數學成績");

                 english=rs.getint("英語成績");

                 out.print("&lt;td &gt;"+english+"&lt;/td&gt;");

                 physics=rs.getint("實體成績");

                 out.print("&lt;td &gt;"+physics+"&lt;/td&gt;");

                 out.print("&lt;/tr&gt;") ; 

               }

     {  }

<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:

&lt;body bgcolor=pink &gt;

&lt;form action="newresult.jsp" method=post&gt;

輸入要修改成績的同學的姓名:&lt;br&gt;

&lt;input type="text" name="name"&gt;

&lt;br&gt;輸入新的數學成績:

&lt;input type="text" name="math"&gt;

&lt;br&gt;輸入新的英語成績:

&lt;input type="text" name="english"&gt;

&lt;br&gt;輸入新的實體成績:

&lt;input type="text" name="physics"&gt;

&lt;br&gt;&lt;input type="submit" name="b" value="送出更新"&gt;

&lt;p&gt;資料庫更新前的資料記錄是:

            out.print("&lt;th width=100&gt;"+"姓名");

&lt;/font&gt;

newresult.jsp:

&lt;body bgcolor=pink &gt;&lt;font size=1&gt;

  &lt;% //擷取送出的姓名:

     //擷取送出的新的數學成績:

    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);

       //顯示更新後的表中的記錄:

     %&gt;

     &lt;p&gt;更新後的表的記錄:

     &lt;%

       rs=sql.executequery("select * from students");

           {

             out.print("&lt;tr&gt;");

                 number=rs.getstring(1);

                 xingming=rs.getstring(2);

                 math=rs.getint("數學成績");

                 out.print("&lt;td &gt;"+english+"&lt;/td&gt;");

            out.print("&lt;/tr&gt;") ; 

     { }

<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:

&lt;p&gt;添加新的記錄到資料庫:

&lt;form action="newdatabase.jsp" method=post&gt;

同學學号:

&lt;input type="text" name="number"&gt;

&lt;br&gt;同學姓名:

&lt;br&gt;數學成績:

&lt;br&gt;英語成績:

&lt;br&gt;實體成績:

&lt;br&gt;&lt;input type="submit" name="b" value="送出添加"&gt;

&lt;p&gt;資料庫添加記錄前的資料記錄是:

    try { con=drivermanager.getconnection("jdbc:odbc:moon","sa","");

         sql=con.createstatement();

newdatabase.jsp:

  &lt;% //擷取送出的學号:

    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); //執行添加操作:

       //顯示添加新記錄後表中的記錄:

     &lt;p&gt;添加新記錄後的表:

       rs=sql.executequery("select * from students order by 學号 ");

           {    out.print("&lt;tr&gt;");

                string n=rs.getstring(1);

                 out.print("&lt;td &gt;"+n+"&lt;/td&gt;");

                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:

&lt;p&gt;删除記錄:

&lt;form action="delete.jsp" method=post&gt;

輸入被删除記錄的學号:

&lt;br&gt;

&lt;br&gt;&lt;input type="submit" name="b" value="送出删除"&gt;

&lt;p&gt;資料庫删除前的資料記錄是:

delete.jsp:

       //删除操作:

       string deleteall="delete  from students where 學号"+" = "+"'"+number+"'";

       sql.executeupdate(deleteall);

      %&gt;

     &lt;p&gt;删除記錄後的表:

                 out.print("&lt;td &gt;"+xingming+"&lt;/td&gt;");

                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所示)

 &lt;%! int pagesize=3; //每頁顯示的記錄數。

     int pagecount=0; //分頁後的總頁數。

&lt;%-- 客戶通過表單送出欲要顯示的頁碼數--%&gt;

&lt;form action="" method=get &gt;

 輸入頁碼數&lt;input type=text name=showpage size=4 &gt;

   &lt;input type=submit name=g value=送出&gt;

 &lt;/form&gt;

&lt;%  connection con;

         int lastrow=rs.getrow();

        //計算分頁後的總頁數:

        pagecount=(lastrow%pagesize==0)?(lastrow/pagesize):(lastrow/pagesize+1);

        //目前顯示的初始頁數:

        int showpage=1;

        //告知客戶總頁數:

        &lt;p&gt; 共有&lt;%=pagecount%&gt;頁

        &lt;br&gt;每頁顯示&lt;%=pagesize%&gt;條記錄.

      &lt;% //擷取客戶想要顯示的頁數:

          string integer=request.getparameter("showpage");

               if(integer==null)

                  { integer="1";

                  }

           try {showpage=integer.parseint(integer); 

           catch(numberformatexception e)

               {showpage=1;

          if(showpage&lt;=1)

             {showpage=1;

             }

          if(showpage&gt;=pagecount)

             {showpage=pagecount;

             }

        &lt;br&gt;目前顯示第&lt;%=showpage%&gt;頁 

      &lt;% //如果要顯示第showpage頁,那麼遊标應移到posion的值是:

         int posion=(showpage-1)*pagesize+1;

          rs.absolute(posion); // 設定遊标的位置

          out.print("&lt;table border&gt;");

          out.print("&lt;tr&gt;");

          out.print("&lt;/tr&gt;");

       for (int i=1;i&lt;=pagesize;i++)

            out.print("&lt;td &gt;"+rs.getint("實體成績")+"&lt;/td&gt;");  

          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:

 &lt;% 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("&lt;th width=100&gt;"+"empno");

            out.print("&lt;th width=50&gt;"+"ename");

             int n=rs.getint(1);

             out.print("&lt;td &gt;"+n+"&lt;/td&gt;");

            string e=rs.getstring(2);

             out.print("&lt;td &gt;"+e+"&lt;/td&gt;");

         out.print("&lt;/tr&gt;") ; 

   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:

 &lt;% connection con; 

     statement sql; 

     resultset rs;

      }

    try { con=drivermanager.getconnection("jdbc:odbc:star","","");

         rs=sql.executequery("select * from 品名 ");

            out.print("&lt;th width=100&gt;"+"品名");

            out.print("&lt;th width=50&gt;"+"機關");

            out.print("&lt;th width=50&gt;"+"單價");

            string name=rs.getstring(1);

            string  unit=rs.getstring(2);

             out.print("&lt;td &gt;"+unit+"&lt;/td&gt;");

            string  unitprice=rs.getstring(3);

            out.print("&lt;td &gt;"+unitprice+"&lt;/td&gt;");

<b>5.10 </b><b>使用同步連接配接</b>

資料庫操作中,建立連接配接是耗時最大的操作之一。如果客戶通路的是同一資料庫,那麼,為每個客戶都建立一個連接配接是不合理的。我們已經知道,在“&lt;%!”和“%&gt;”之間聲明的變量在整個jsp頁面内都有效,因為jsp引擎将jsp頁面轉譯成java檔案時,将這些變量作為類的成員變量。這些變量的記憶體空間直到伺服器關閉才釋放。當多個客戶請求一個jsp頁面時,jsp引擎為每個客戶啟動一個線程而不是啟動一個程序,這些線程由web伺服器程序來管理,它們共享jsp頁面的成員變量。在處理多線程問題時,可以将線程共享的變量放入一個synchronized塊,或将修改該變量的方法用synchronized來修飾,這樣,當一個客戶用synchronized塊或synchronized方法修改一個共享變量時,其它線程就必須等待,直到該線程執行完該方法或同步塊。這樣,我們可以把connection對象作為一個成員變量被所有的客戶共享,也就是說第一個通路資料庫的客戶負責建立連接配接,以後所有的客戶共享這個連接配接,每個客戶都不要關閉這個共享的連接配接。

<b>例子13</b>(效果如圖5.34、5.35所示)

example5_13.jsp:

 &lt;%! //聲明一個共享的連接配接對象:

  %&gt;

 &lt;% 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("&lt;table border&gt;");

           string  number=rs.getstring(1);

           string  name=rs.getstring(2);

           int  math=rs.getint("數學成績");

           int  english=rs.getint("英語成績");

             out.print("&lt;td &gt;"+english+"&lt;/td&gt;");

           int  physics=rs.getint("實體成績");

        out.print("&lt;/tr&gt;") ;         

      out.print("&lt;/table&gt;");

    }