JSP中使用数据库.docx
《JSP中使用数据库.docx》由会员分享,可在线阅读,更多相关《JSP中使用数据库.docx(72页珍藏版)》请在冰豆网上搜索。
JSP中使用数据库
第5章JSP中使用数据库
在JSP中可以使用Java的JDBC技术,实现对数据库中表记录的查询、修改和删除等操作。
JDBC技术在JSP开发中占有很重要的地位。
JDBC(JavaDataBaseConnectivity)是Java数据库连接API。
简单地说,JDBC能完成三件事:
(1)与一个数据库建立连接,
(2)向数据库发送SQL语句,
(3)处理数据库返回的结果。
JDBC在设计上和ODBC很相似。
JDBC和数据库建立连接的一种常见方式是建立起一个JDBC─ODBC桥接器。
由于ODBC驱动程序被广泛的使用,建立这种桥接器后,使得JDBC有能力访问几乎所有类型的数据库。
JDBC也可以直接加载数据库驱动程序访问数据库,我们将在2.8节讨论。
如果使用JDBC─ODBC桥接器访问数据库,事先必须设置数据源。
5.1数据源
假设要访问SQLServer服务器上的pubs数据库,该库有一个表students,如图5.1、5.2所示。
为连接一个SQL-Server数据库,我们需设置一个数据源。
在控制面板选择ODBC数据源,如图5.3所示。
双击ODBC数据源图标。
出现如图5.4所示界面,图5.4中显示了用户已有的数据源的名称。
选择“用户DSN”,点击add按钮,增加新的数据源。
如图5.5所示:
为新增的数据源选择驱动程序,因为要访问SQLServer数据库,选择SQLServer,点击完成按钮(为数据源选择了驱动程序),出现设置数据源具体项目的对话框,如图5.6所示。
在名称栏里为数据源起一个你自己喜欢的名字,这里我们起的名字是sun(当然,如果你喜欢的话,可以把名字叫做moon.)。
这个数据源就是指某个数据库(将来随着计算机的进步,我们也可能有能力把数据源设成是一个卫星上来的信号)。
在“你想连接哪个SQLServer?
”栏中选择或输入一个数据库服务器,这里我们选择了网络上的另一台机器:
Ping。
单击“下一步”出现图5.7画面,选择连接SQLServer的ID。
在图5.7的对话框中,选择“使用用户输入登录标识号和密码的SQLServer验证”选项,在这里我们选择用户名为sa(不需要密码),单击“下一步”出现如图5.8所示的选择数据库的对话框。
选中“改变默认的数据库为”复选框,在下拉菜单里,我们选择用户sa有权限操作的数据库pubs。
单击“下一步”出现完成数据源设置的对话框如图5.9。
在图5.9中,单击“完成”出现你所配置的数据源的信息窗口,如图5.10所示。
点击“测试数据源”按钮,如果正常就会出现数据源设置成功的窗口,如图5.11所示。
5.2JDBC-ODBC桥接器
现在你可以这样的直观理解:
我们有了一个数据源,这个数据源就是一个数据库。
为了要连接到这个数据库,需要建立一个JDBC─ODBC桥接器,即加载桥接器驱动程序。
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
这里,Class是包java.lang中的一个类,该类通过调用它的静态方法forName就可以建立JDBC-ODBC桥接器。
建立桥接器时可能发生异常,所以建立桥接器的标准是:
try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(ClassNotFoundExceptione)
{}
5.3查询记录
要查询数据库中的记录,必须和数据库建立连接,由于使用的是JDBC-ODBC方式访问数据库,那么就要与数据源建立连接。
(1)连接到数据库
首先使用包java.sql中的Connection类声明一个对象,然后再使用类DriverManager调用它的静态方法getConnection创建这个连接对象:
Connectioncon=DriverManager.getConnection("jdbc:
odbc:
数据源名字","loginname","password");
假如您没有为数据源设置loginname和password,那么连接形式是:
Connectioncon=DriverManager.getConnection("jdbc:
odbc:
数据源名字","","");
与数据库pubs(它就是数据源sun)建立连接,格式如下:
try{Connectioncon=DriverManager.getConnection("jdbc:
odbc:
sun","sa","");
}
catch(SQLExceptione)
{}
这样就建立了到数据库pubs的连接。
(2)向数据库发送SQL语句。
首先使用Statement声明一个SQL语句对象,然后通过刚才创建的连接数据库的对象con调用方法createStatment()创建这个SQL语句对象。
try{Statementsql=con.createStatement();}
catch(SQLExceptione){}
(3)处理查询结果
有了SQL语句对象后,这个对象就可以调用相应的方法实现对数据库中表的查询和修改。
并将查询结果存放在一个ResultSet类声明的对象中,也就是说SQL语句对数据库的查询操作将返回一个ResultSet对象:
ResultSetrs=sql.executeQuery("SELECT*FROM成绩表");
ResultSet对象是以统一形式的列组织的数据行组成。
ResultSet对象一次只能看到一个数据行,使用next()方法走到下一数据行,获得一行数据后,ResultSet对象可以使用getxxxx方法获得字段值,将位置索引(第一列使用1,第二列使用2等等)或字段名传递给getxxxx方法的参数即可。
ResultSet类的若干方法
●booleannext()
●bytegetByte(intcolumnIndex)
●DategetDate(intcolumnIndex)
●doublegetDouble(intcolumnIndex)
●floatgetFloat(intcolumnIndex)
●intgetInt(intcolumnIndex)
●longgetLong(intcolumnIndex)
●StringgetString(intcolumnIndex)
●bytegetByte(StringcolumnName)
●DategetDate(StringcolumnName)
●doublegetDouble(StringcolumnName)
●floatgetFloat(StringcolumnName)
●intgetInt(StringcolumnName)
●longgetLong(StringcolumnName)
●StringgetString(StringcolumnName)
5.3.1顺序查询
使用结果集Result的next()方法,可以顺序的查询。
一个结果集将游标最初定位在第一行的前面,第一次调用next()方法使游标移动到第一行。
next()方法返回一个boolean型数据,当游标移动到最后一行之后返回false。
在下面的例子1中,我们查询数据库pubs(数据源sun)中students表里的包含全部字段的记录。
例子1(效果如图5.12所示)
Example5_1.jsp:
<%@pagecontentType="text/html;charset=GB2312"%>
<%@pageimport="java.sql.*"%>
<%Connectioncon;
Statementsql;
ResultSetrs;
try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(ClassNotFoundExceptione){}
try{con=DriverManager.getConnection("jdbc:
odbc:
sun","sa","");
sql=con.createStatement();
rs=sql.executeQuery("SELECT*FROMstudents");%>
学号
数学成绩
英语成绩
物理成绩
|
<%while(rs.next())
{out.print("
");out.print("
"+rs.getString (1)+" | ");out.print("
"+rs.getString (2)+" | ");out.print("
"+rs.getInt("数学成绩")+" | ");out.print("
"+rs.getInt("英语成绩")+" | ");out.print("
"+rs.getInt("物理成绩")+" | ");out.print("
");
}
out.print("");
con.close();
}
catch(SQLExceptione1){}
%>
在下面的例子2中查询“英语成绩”字段值大于80的记录,但只显示“姓名”字段(第2个字段)和“英语成绩”字段。
例子2(效果如图5.13所示)
Example5_2.jsp:
<%@pagecontentType="text/html;charset=GB2312"%>
<%@pageimport="java.sql.*"%>
<%Connectioncon;
Statementsql;
ResultSetrs;
try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(ClassNotFoundExceptione){}
try{con=DriverManager.getConnection("jdbc:
odbc:
sun","sa","");
sql=con.createStatement();
rs=sql.executeQuery("SELECT*FROMstudentsWHERE英语成绩>=80");
out.print("");
out.print("
");out.print(""+"姓名");
out.print(""+"英语成绩");
out.print("
");
while(rs.next())
{out.print("
");out.print("
"+rs.getString (2)+" | ");out.print("
"+rs.getInt("英语成绩")+" | ");out.print("
");
}
out.print("");
con.close();
}
catch(SQLExceptione1){}
%>
5.3.2游动查询
前面我们学习了使用Result的next()方法顺序地查询数据,但有时候我们需要在结果集中前后移动、或显示结果集指定的一条记录等等。
这时,我们必须要返回一个可滚动的结果集。
为了得到一个可滚动的结果集,和上一节不同的是,我们必须使用下述方法先获得一个Statement对象:
Statementstmt=con.createStatement(ResultSet.TYPE_FORWORD_ONLY,intconcurrency);
然后,根据参数的type、concurrency的取值情况,stmt返回相应类型的结果集:
ResultSetre=stmt.executeQuery(SQL语句);
type的取值决定滚动方式,取值可以是:
●ResultSet.TYPE_FORWORD_ONLY:
结果集的游标只能向下滚动。
●ResultSet.TYPE_SCROLL_INSENSITIVE:
结果集的游标可以上下移动,当数据库变化时,当前结果集不变。
●ResultSet.TYPE_SCROLL_SENSITIVE:
返回可滚动的结果集,当数据库变化时,当前结果集同步改变。
Concurrency取值决定是否可以用结果集更新数据库,Concurrency取值:
●ResultSet.CONCUR_READ_ONLY:
不能用结果集更新数据库中的表。
●ResultSet.CONCUR_UPDATETABLE:
能用结果集更新数据库中的表。
滚动查询经常用到ResultSet的下述方法:
●publicbooleanprevious():
将游标向上移动,该方法返回boolean型数据,当移到结果集第一行之前时返回false.
●publicvoidbeforeFirst:
将游标移动到结果集的初始位置,即在第一行之前。
●publicvoidafterLast():
将游标移到结果集最后一行之后。
●publicvoidfirst():
将游标移到结果集的第一行。
●publicvoidlast():
将游标移到结果集的最后一行。
●publicbooleanisAfterLast():
判断游标是否在最后一行之后。
●publicbooleanisBeforeFirst():
判断游标是否在第一行之前
●publicbooleanifFirst():
判断游标是否指向结果集的第一行。
●publicbooleanisLast():
判断游标是否指向结果集的最后一行。
●publicintgetRow():
得到当前游标所指行的行号,行号从1开始,如果结果集没有行,返回0
●publicbooleanabsolute(introw):
将游标移到参数row指定的行号。
注意,如果row取负值,就是倒数的行数,absolute(-1)表示移到最后一行,absolute(-2)表示移到倒数第2行。
当移动到第一行前面或最后一行的后面时,该方法返回false。
在下面的例子中,首先将游标移动到最后一行,然后再获取行号,这样就获得表中的记录数目。
然后我们倒序输出结果集中的记录,即首先输出最后一行。
最后单独输出第5条记录。
例子3(效果如图5.14所示)
Example5_3.jsp:
<%@pagecontentType="text/html;charset=GB2312"%>
<%@pageimport="java.sql.*"%>
<%Stringname,number;
intmath,physics,english;
Connectioncon;
Statementsql;
ResultSetrs;
try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(ClassNotFoundExceptione){}
try{con=DriverManager.getConnection("jdbc:
odbc:
sun","sa","");
sql=
con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
//返回可滚动的结果集:
rs=sql.executeQuery("SELECT*FROMstudents");
//将游标移动到最后一行:
rs.last();
//获取最后一行的行号:
intlownumber=rs.getRow();
out.print("该表共有"+lownumber+"条记录");
out.print("
现在逆序输出记录:
");
out.print("");
out.print("
");out.print(""+"学号");
out.print(""+"姓名");
out.print(""+"数学成绩");
out.print(""+"英语成绩");
out.print(""+"物理成绩");
out.print("
");
//为了逆序输出记录,需将游标移动到最后一行之后:
rs.afterLast();
while(rs.previous())
{out.print("
");number=rs.getString
(1);
out.print("
"+number+" | ");name=rs.getString
(2);
out.print("
"+name+" | ");math=rs.getInt("数学成绩");
out.print("
"+math+" | ");english=rs.getInt("英语成绩");
out.print("
"+english+" | ");physics=rs.getInt("物理成绩");
out.print("
"+physics+" | ");out.print("
");
}
out.print("");
out.print("单独输出第5条记录
");
rs.absolute(5);
number=rs.getString
(1);
out.print(number+",");
name=rs.getString
(2);
out.print(name+",");
math=rs.getInt("数学成绩");
out.print(math+",");
english=rs.getInt("英语成绩");
out.print(english+",");
physics=rs.getInt("物理成绩");
out.print(physics+"。
");
con.close();
}
catch(SQLExceptione1){}
%>
5.3.3随机查询
在下面的例子中,我们随机从结果集中取出4条记录,并计算4条记录的数学成绩的平均值。
用Math类的静态方法random()可以产生一个大于0小于1的随机数,再用下述公式:
inti=(int)(Math.random()*number+1);
产生一个1到number之间的随机数,根据这个随机数将游标移动到相应的行,并输出该行,算法的进一步细节可见下述例子4。
例子4(效果如图5.15所示)
Example5_4.jsp:
<%@pagecontentType="text/html;charset=GB2312"%>
<%@pageimport="java.sql.*"%>
<%Stringxuehao,name;
intmath;
Connectioncon;
Statementsql;
ResultSetrs;
try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(ClassNotFoundExceptione){}
try{con=DriverManager.getConnection("jdbc:
odbc:
sun","sa","");
sql=
con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
//返回可滚动的结果集:
rs=sql.executeQuery("SELECT*FROMstudents");
out.print("");
out.print("
");out.print(""+"学号");
out.print(""+"姓名");
out.print(""+"数学成绩");
out.print("
");
//将游标移动到最后一行:
rs.last();
//获取最后一行的行号:
intlownumber=rs.getRow();
//获取记录数:
intnumber=lownumber;
doublesum=0;
int抽取数目=4;
intold_i[]={0,0,0,0};
intk=抽取数目;
intj=0;
while(抽取数目>0)
{inti=(int)(Math.random()*number+1);//随机获取一个1到number之间的数。
booleanboo=false;
for(intm=0;m{if(i==old_i[m])
boo=true;
}
if(boo)continue;//假如该行已被取出,结束本次循环,继续产生随机数。
rs.absolute(i);//游标移到这一行。
out.print("
");xuehao=rs.getString
(1);//获取该行学号字段的值。
out.print("
"+xuehao+" | ");name=rs.getString
(2);//获取该行姓名字段的值。
out.print("
"+name+" | ");math=rs.getInt("数学成绩");//获取改行数学成绩字段的值。
out.print("
"+math+" | ");out.print("
");
sum=sum+math;
抽取数目--;
o