版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第11章基于JSP的数据库应用开发11.1JDBC接口11.2数据查询11.3数据添加11.4数据删除11.5数据更新11.6数据库连接池【学习提示】数据库实现对数据的存储、管理和检索,因而企业级的Web应用系统以及电子商务系统和电子政务系统均离不开数据库。本章将详细阐述在JSP中采用JDBC实现对数据库的查询、更新、插入和删除等操作,并结合Servlet展示具体的开发实例。读者可以结合JavaBean编写基于JSP的数据库应用程序。
Java数据库连接(JavaDataBaseConnectivity,JDBC)是一种用于执行数据库访问的Java语言应用程序接口(API)。JDBC通过一组Java类和接口,为开发人员提供多种关系型数据库的统一访问方式。JDBC的结构如图11-1所示。11.1JDBC接口
图11-1JDBC的结构JDBC扩展了Java的功能。例如,用Java和JDBCAPI可以发布含有applet的网页,而该applet使用的信息可能来自远程数据库。企业也可以用JDBC通过Intranet将所有职员连到一个或多个内部数据库中(即使这些职员所用的计算机有Windows、Macintosh和UNIX等各种不同的操作系统)。
开发人员可以通过JDBC的API来动态加载合适的JDBC驱动程序,并在JDBC驱动程序管理器(JDBCDriverManager)中进行注册,而驱动程序管理器以工厂模式创建数据库的JDBC连接。11.1.1JDBC的功能
JDBC的具体功能可以归纳为以下三方面:
(1)与数据库建立连接,具体代码如下:
//动态加载JDBC驱动程序
//在JDBC4.0之后不再需要Class.forName()来加载驱动程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//创建数据库的JDBC连接
Connectionconn=DriverManager.getConnection("jdbc:odbc:Database");(2)向数据库发送SQL语句。JDBC可以将SQL语句通过驱动程序传递给数据库服务器去执行,其中INSERT、UPDATE和DELETE等语句会对数据产生修改并通过JDBC返回修改的行数,而SELECT语句则会在数据库中进行查询并返回结果行的集合。具体代码如下:
Statementstmt=con.createStatement();
ResultSetrs=stmt.executeQuery("SELECTa,b,cFROMtable1");
(3)处理数据库返回的结果,具体代码如下:
while(rs.next())
System.out.println(rs.getString(1)+""+re.getString(2));11.1.2JDBC驱动分类
JDBC驱动是连接数据库的基础。它实现了在客户和数据库之间传递SQL语句和执行结果信息。目前的JDBC驱动程序可以分为以下四类:
1.JDBC-ODBC桥驱动
JDBC-ODBC桥利用ODBC驱动程序提供JDBC访问。JDBC-ODBC桥是比较通用的数据库接口,其体系结构如图11-2所示。它利用了微软ODBC的开放性,只要本地机装有ODBC驱动,采用JDBC-ODBC桥驱动几乎可以访问所有类型的数据库。对于已经安有ODBC驱动的客户端,这种数据库访问方式也是可行的。
图11-2JDBC-ODBC桥的原理图使用JDBC-ODBC桥连接访问数据库,先要建立数据源(DataSourceName,DSN),每个数据源对应一个数据库。Java程序要连接到数据库,需要建立一个JDBC-ODBC桥接器,也就是加载JDBC-ODBC桥驱动程序。
下面以学生课程成绩管理的SC数据库为例,说明如何利用JDBC-ODBC桥建立数据库连接。
(1)在Access中创建数据库SC,该数据库包含三个数据表,即Student、Course和SG,每个表的关系模型见表11-1、表11-2及表11-3。表11-1Student表的属性结构表11-2Course表的属性结构表11-3SG表的属性结构
在SC数据库中输入数据。Student、Course、SG表的数据分别如图11-3、图11-4、图11-5所示。
图11-3Student表中的数据图11-4Course表中的数据
图11-5SG表中的数据(2)为数据库SC建立一个数据源。一个数据源就是对数据库的一个命名连接。数据源有三种:用户数据源、系统数据源和文件数据源。用户数据源只有用户可以看见,只能用于当前机器中。系统数据源是允许任何具有权限的用户都可以访问的数据源。文件数据源把信息存储在后缀为
.dsn的文本文件中,如果把该文件放在网络共享目录中,则可被网络中任何一台工作站访问。Web应用程序访问数据库时,通常是建立系统数据源。下面为数据库SC创建一个名为SCdsn的系统数据源,具体操作步骤如下:
①打开“控制面板”→“管理工具”→“数据源(ODBC)”,选择“系统DSN”选项卡,如图11-6所示。
②单击“添加”按钮,弹出“创建新数据源”对话框,如图11-7所示。
图11-6ODBC数据源管理器
图11-7创建新数据源
③选择DriverdoMicrosoftAccess,单击“完成”按钮。
④弹出“ODBCMicrosoftAccess安装”窗口,如图11-8所示。在“数据源名”文本框中输入数据源名称“SCdsn”,单击“选择”按钮,弹出如图11-9所示的“选择数据库”窗口。
图11-8创建Access的新数据源
图11-9选择数据库
⑤在弹出的窗口中选择刚才创建的Access数据库SC.mdb,单击“确定”按钮,返回“ODBCMicrosoftAccess安装”窗口,单击“高级”按钮,弹出如图11-10所示的“设置高级选项”窗口,可以为SCdsn数据源设置登录名称和密码。我们在这里不设置登录名称和密码,单击“取消”按钮,返回“ODBCMicrosoftAccess安装”窗口。
图11-10设置高级选项
⑥单击“确定”按钮,返回“ODBC数据源管理器”窗口,此时可以看到在窗口中显示系统数据源SCdsn,如图11-11所示。
图11-11数据源SCdsn创建成功(3)在Java程序中运用JDBC-ODBC桥连接SC数据库。具体步骤如下:
①引入sql包。例如:
importjava.sql.*;
②加载JDBC-ODBC桥驱动程序。例如:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
③建立与数据库的连接。例如:
Connectionconn=DriverManager.getConnection("jdbc:odbc:SCdsn","","");
getConnection方法的后两个参数分别是数据源的登录名称和密码,如果没有设置,则为空。图11-12本地API驱动结构图2.本地API驱动
此类型的驱动程序把客户机API上的JDBC调用转换为对Oracle、Sybase、DB2或其他DBMS的调用,还需要下载不同类型数据库的驱动代码,其结构如图11-12所示。这种驱动比JDBC-ODBC桥执行效率有很大的提高。但是,它仍然需要在客户端加载数据库厂商提供的代码库,不适合基于Internet的应用。并且,其执行效率比第3种和第4种JDBC驱动都低。下面以SQLServer数据库为例,说明使用本地API驱动连接数据库的具体过程。
(1)首先到微软的驱动下载地址http://www./zh-cn/download/driver.aspx?q=driver选择合适的驱动程序进行下载,本书下载的版本为MicrosoftSQLServerJDBCDriver2.0。
(2)解压下载的文件,里面有两个JAR文件,即sqljdbc.jar和sqljdbc4.jar,如图11-13所示,两个文件的不同之处是:
①sqljdbc.jar类库要求使用5.0版的Java运行时环境(JRE)。连接到数据库时,在JRE6.0上使用sqljdbc.jar会引发异常。
图11-13SQLServerJDBC驱动程序②sqljdbc4.jar类库提供对JDBC4.0的支持。它不仅包括sqljdbc.jar的所有功能,还包括新增的JDBC4.0方法。sqljdbc4.jar类库要求使用6.0或更高版本的Java运行时环境(JRE)。在JRE1.4或5.0上使用sqljdbc4.jar会引发异常。
(3)为SQLServer的JDBC驱动程序配置环境变量。由于本书采用JDK1.6的版本,所以在classpath后面追加参数如下:
D:\ProgramFiles\sqljdbc_2.0\sqljdbc4.jar(4)设置SQLServer的参数。
①打开SQLServerConfigurationManager。
②打开SQLServer2005网络配置→MSSQLSERVER的协议→TCP/IP,双击进入,在IP地址一栏中,把相应的端口号改成1433,再重启。
(5)在SQLServer2005中创建数据库SC,与该数据库建立连接的代码如下:
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connectioncon=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;
DatabaseName=SC","sa","");
getConnection()方法的三个参数分别表示“连接服务器的URL和数据库名称”、“SQLServer用户名”和“密码”。3.网络协议驱动
这种类型的驱动把对数据库的访问请求传递给网络上的中间件服务器,中间件服务器把请求翻译为符合数据库规范的调用,再把这种调用传给数据库服务器,具体结构如图11-14所示。
由于这种驱动是基于server的,所以不需要在客户端加载数据库厂商提供的代码库。而且它在执行效率和可升级性方面是比较好的。因为大部分功能实现都在server端,所以这种驱动设计得很小,能够非常快速地加载到内存中。但是,这种驱动在中间件层仍然需要配置其他数据库驱动程序,并且由于多了一个中间层传递数据,因而它的执行效率还不是最好。4.本地协议驱动
这种类型的驱动程序将JDBC调用直接转换为DBMS所使用的网络协议,其结构如图11-15所示。这将允许从客户机器上直接调用DBMS服务器,是Intranet访问的一个很实用的解决方法。
图11-14网络协议驱动结构
图11-15本地协议驱动结构11.1.3JDBC访问数据库的基本步骤
在Java程序中通过JDBC操作数据库一般分为以下几个步骤:
(1)如果采用本地API驱动,则要把数据库的JDBC驱动加载到classpath中,或把驱动复制到Web应用的WEB-INF/lib目录下,并在编写代码时引入sql包,即java.sql.*。
(2)加载JDBC驱动,并将其注册到DrvierManager中。例如:
//JDBC-ODBC桥
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//SQLServer2000数据库
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
//SQLServer2005数据库
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
//MySQL数据库
Class.forName("com.mysql.jdbc.Driver");(3)建立与数据库的连接,取得Connection对象。例如:
//JDBC-ODBC桥
Connectionconn=DriverManager.getConnection("jdbc:odbc:SCdsn","","");
//SQLServer数据库(SQLServer2000和SQLServer2005均适用)
Stringurl="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=SC";Stringuser="sa";
Stringpassword="";
Connectionconn=DriverManager.getConnection(url,user,password);
//MySQL数据库
Stringurl="jdbc:mysql://localhost:3306/SC?user=root&password=your_password";
Connectionconn=DriverManager.getConnection(url);(4)创建Statement对象或PreparedStatement对象。在数据库连接成功之后,就可以执行具体的SQL语句。但在执行SQL语句之前,必须先创建一个对象,用于将SQL语句发送到数据库中,执行对数据库的检索或更新。目前JDBC提供了下列三种不同类型的对象:
①Statement:该对象提供了直接在数据库中执行SQL语句的方法。对于只执行一次的查询及数据定义语句如CREATETABLE、DROPTABLE等操作,Statement对象就足够了。其语法结构如下:Statementstmt=conn.createStatement();
②PreparedStatement:该对象用于那些需要执行多次,每次仅仅是数据取值不同的SQL语句。PreparedStatement对象具有预编译功能,对批量数据操作的执行效率较高。其语法格式如下:
PreparedStatementps=conn.prepareStatement("INSERTintoemployeesvalues(?,?,?)");
?代表具体要输入的参数。
③CallableStatement:该对象被用来访问数据库中的存储过程。它提供了一些方法来指定SQL语句所有使用的输入输出参数。语法格式如下:CallableStatementcstmt=con.prepareCall("{callgetTestData(?,?)}");
注意:不同类型的数据库只是在加载驱动和建立连接时输入的参数不同,后面发送和执行SQL语句都是相同的。
(5)用Statement或PreparedStatement对象的方法执行SQL语句。执行SQL语句分查询和更新(包括insert、delet、update)两种情况,下面分别介绍:
①执行SQL查询语句,首先要创建一个用于存放查询结果的ResultSet(结果集)对象,例如:ResultSetrs=stmt.executeQuery("SELECT*FROMstudent");
②执行insert、delete、update等SQL语句,这三种SQL语句只有操作成功与否,不返回结果集,语法格式如下:
stmt.executeUpdate(sql);
其中,sql代表具体的insert、delete、update语句。例如:
stmt.executeUpdate("DELETEFROMSGWHERECno='2'andSno='200212121'");(6)针对查询语句,访问结果记录集ResultSet对象。ResultSet包含任意数量的命名列,可以按名字或序号访问这些列;还包含一或更多个行,可以按顺序自上而下逐一访问。当建立一个ResultSet类对象时,它指向第一行之前的位置。ResultSet对象的常用方法如下:
●
getString(int):将序号为int列的内容作为字符串返回。
●
getString(String):将名称为String列的内容作为字符串返回。●
getInt(int):将序号为int列的内容作为整数返回。
●
getInt(String):将名称为String列的内容作为整数返回。
●
getFloat(int):将序号为int列的内容作为一个float型数返回。
●
getFloat(String):将名称为String列的内容作为一个float型数返回。
●
getData(int):将序号为int列的内容作为日期返回。
●
getData(String):将名称为String列的内容作为日期返回。●
next():把行指针移到下一行,如果没有剩余行,则返回false。
●
close():关闭结果集。
例如,根据步骤(5)中的查询结果,要输出所有学生的姓名,可以使用如下代码:
while(rs.next()){
Stringname=rs.getString("name");//由于name属性在第二列,上条语句也可以写成Stringname=rs.getString(2);
our.println(name+"<br>");
}
上述代码采用循环语句将查询结果集逐行遍历,直到rs.next()返回false,即行指针到最后一行为止。(7)依次将ResultSet、Statement、PreparedStatement和Connection对象关闭,释放所占用的资源。例如:
rs.close();//关闭ResultSet对象
stmt.close();//关闭Statement对象
conn.close();//关闭Connection对象
下面我们将通过实例详细讲解在Web开发中使用JDBC访问数据库的用法与基本模式。在本实例中采用Servlet
+
JavaScript
+
JSP实现同一个页面(student.jsp)中对Student表的查询、插入、删除和修改。本例中所用的各程序间的结构关系如图11-16所示;student.jsp的首次运行结果如图11-17所示。
图11-16实例中各程序间的结构关系图
图11-17student.jsp的首次运行结果
对Student表的查询在sutdent.jsp页面中可实现,具体代码如下(其中黑体代码运用JDBC-ODBC桥对Student表进行查询):
student.jsp
<%@pageimport="java.sql.*"%>
<%@pagelanguage="java"import="java.util.*"pageEncoding="GBK"%>11.2数据查询<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
<html>
<head>
<title>对Student表的数据操作</title>
<!--下一行代码链入外部样式表文件style.css,该样式表主要规定了表格中单元格大小和对齐方式-->
<linkrel="stylesheet"type="text/css"href="css/style.css"><!--下面的代码插入JavaScript脚本-->
<scripttype="text/javascript">
/*函数process()的功能是当客户点击每一条数据后面的“修改”按钮后,取消原有的“删除”
和“修改”按钮,增加“提交”和“取消”按钮,并定义这两个按钮的功能。*/
functionprocess(obj){
selectedIndex=;
hideDelEditAndInserInput(obj,1);
//插入提交和取消按钮 varnode=document.createElement("input");
node.type="button";
node.value="取消";
node.onclick=function(){
varobjtemp=document.getElementById("edit"+selectedIndex).parentNode;
objtemp.removeChild(objtemp.childNodes[1]);
objtemp=document.getElementById("del"+selectedIndex).parentNode; objtemp.removeChild(objtemp.childNodes[1]);
dispDelEditAndReview();
};
varobjpar=obj.parentNode;
objpar.appendChild(node);
node=document.createElement("input");
node.type="button";
node.value="提交";
node.onclick=function(){
form0.no.value=tdNodes[0].childNodes[1].value;
.value=tdNodes[1].childNodes[1].value;
form0.sex.value=tdNodes[2].childNodes[1].value;
form0.age.value=tdNodes[3].childNodes[1].value;
form0.dept.value=tdNodes[4].childNodes[1].value;
form0.submit();
};
objpar=document.getElementById("del"+).parentNode;
objpar.appendChild(node);
}
//函数deleteLine()的功能是通过向Servlet发送请求数据实现删除数据的功能
functiondeleteLine(no){
window.location.href="servlet/serStudent?act=delete&no="+no;
}
</script>
<!--下一行代码引入JavaScript文件script.js,其中的函数在process(obj)中使用--><scripttype="text/javascript"src="js/script.js"></script>
</head>
<body>
<h3>Student表中的数据信息</h3>
<!--下面的form0是一个隐藏的表单,主要用于“修改”操作时将修改后的数据提交给Servlet
处理-->
<formname="form0"method="post"action="servlet/serStudent?act=update"> <inputtype="hidden"name="no"/><inputtype="hidden"name="name"/>
<inputtype="hidden"name="sex"/><inputtype="hidden"name="age"/>
<inputtype="hidden"name="dept"/>
</form>
<!--下面的table用于显示Student数据的表格-->
<tablecellspacing=0border=1width=700>
<tr>
<td></td> <td>学号</td>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>所在系</td>
<td></td>
<td></td>
</tr><!--表单form1用于“新增”数据时,输入数据值,并将数据提交给Servlet处理-->
<formname="form1"action="servlet/serStudent?act=insert"method="post">
<tr>
<td></td>
<td><inputtype="text"id="no"name="no"/>
</td>
<td><inputtype="text"id="name"name="name"/>
</td> <td><inputtype="text"id="sex"name="sex"/>
</td>
<td><inputtype="text"id="age"name="age"/>
</td>
<td><inputtype="text"id="dept"name="dept"/>
</td>
<td><inputtype="submit"value="新增"/>
</td>
</tr>
</form> <%
//与数据库建立连接以及查询时用到的三个对象
Connectionconn=null;
Statementstate=null;
ResultSetrs=null;
try{
//加载JDBC-ODBC桥驱动程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//通过ODBC数据源SCdsn与Access数据库SC建立连接
conn=DriverManager.getConnection("jdbc:odbc:SCdsn","","");
state=conn.createStatement();
Stringsql="select*fromStudent";
//对Student表执行Select查询语句
rs=state.executeQuery(sql);
intcount=0;
//使用next方法对查询结果集rs进行逐行遍历,并获取每个属性的值
while(rs.next()){
Stringno=rs.getString("Sno");
Stringname=rs.getString("name");
Stringsex=rs.getString("sex");
Stringdept=rs.getString("department");
intage=rs.getInt("age");
%>
<!--下面的tr将从rs中获取的一个元组(即一个学生)的5个属性值通过表格中一行数
据显示给客户-->
<tr>
<!--count用于给每一行数据加一个行号(索引)-->
<td><%=++count%></td>
<tdclass="td<%=count%>"><%=no%></td>
<tdclass="td<%=count%>"><%=name%></td>
<tdclass="td<%=count%>"><%=sex%></td>
<tdclass="td<%=count%>"><%=age%></td>
<tdclass="td<%=count%>"><%=dept%></td>
<!--input标签的作用在每行数据后面增加一个“删除”按钮--> <td><inputclass="del"type="button"value="删除"id="del<%=count%>"onclick="javascript:deleteLine(<%=no%>)"/></td>
<!--下面input标签的功能是在“删除”按钮后面再增加一个“修改”按钮-->
<td><inputclass="edit"type="button"value='修改'id="edit<%=count%>"onclick="process(this)"name="<%=count%>"/></td>
</tr> <%
}
}catch(Exceptione){
e.printStackTrace();
}finally{
try{
//下面依次关闭前面创建的三个对象rs、state和conn
if(rs!=null)
rs.close(); if(state!=null)
state.close();
if(conn!=null)
conn.close();
}catch(SQLExceptione){
e.printStackTrace();
}
}
%>
</table></body>
</html>
通过上面对student.jsp源代码的分析可以看出该页面综合运用了CSS、JavaScript、HTML、JSP和JDBC-ODBC桥技术实现对Student表的查询,并将查询结果以表格形式在客户端浏览器上进行显示,同时为客户提供进行数据添加、数据删除和数据更新的操作按钮和数据输入框。每一行数据后面都有一个删除和修改按钮。在后面将详细讲解如何实现对Student表中数据的添加、删除和修改。Student.jsp链入的css文件style.css的代码如下:
tabletrtd{
width:130px;
height:30px;
text-align:center;}
样式表文件style.css规定了表格中单元格的宽度、高度以及文本居中的对齐方式。
当客户端需要在Student表中增加一名新学生的信息时,可以在图11-17所示的student.jsp页面上增加数据的文本框,并输入新增学生的信息,确保学号的取值不能为空,如图11-18所示。信息输入完成后,单击“新增”按钮,Tomcat服务器对Student表执行数据添加操作,并向客户端返回Student表的所有数据,执行结果如图11-19所示,其中第6行数据是新增的学生信息。11.3数据添加
图11-18输入新增的学生信息
图11-19执行数据添加操作后的运行结果用于让用户输入新增数据值的表单代码段如下:
<formname="form1"action="servlet/serStudent?act=insert"method="post">
<tr>
<td></td>
<td><inputtype="text"id="no"name="no"/>
</td>
<td><inputtype="text"id="name"name="name"/>
</td>
<td><inputtype="text"id="sex"name="sex"/>
</td> <td><inputtype="text"id="age"name="age"/>
</td>
<td><inputtype="text"id="dept"name="dept"/>
</td>
<td><inputtype="submit"value="新增"/>
</td>
</tr>
</form>表单form1中的文本输入框和“新增”按钮作为表格中的一行显示在客户端浏览器上。从表单的属性可以获悉,用户输入数据后以post方式提交给名为serStudent的Servlet处理,同时还以在URL后面追加参数名和参数值的方式向serStudent发送属性act及其值“insert”。serStudent的具体代码如下:
serStudent.java
//为serStudent定义包servlet
packageservlet;//引入serStudent要用到的类
importjava.io.IOException;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.SQLException;
importjava.sql.Statement;
//下面是serStudent作为servlet要引入的类
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassserStudentextendsHttpServlet{
//实现序列化类的不同版本间的兼容性
privatestaticfinallongserialVersionUID=1L;
//下面是serStudent的构造方法,继承父类的构造方法
publicserStudent(){
super();
}//下面是serStudent的初始化方法
publicvoidinit()throwsServletException{
//Putyourcodehere
}
//下面serStudent重写doGet方法:直接调用doPost方法
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
this.doPost(request,response);
}//下面serStudent重写doPost方法
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
request.setCharacterEncoding("GBK");
//conn用于与数据库SC建立连接的对象
Connectionconn=null;
//state用于发送和执行SQL语句的对象
Statementstate=null;
Stringsql="";//下面采用request的getParameter()方法获取客户端发送过来的属性act的值
Stringaction=request.getParameter("act");
if(action!=null){
System.out.print(action);
//下面依次获取由表单提交过来的Student表所需的五个属性的值
Stringno=request.getParameter("no");
Stringname=request.getParameter("name");
StringstrAge=request.getParameter("age");
intage=0;/*由于Student表中age属性的数据类型为整型,所以要将字符串类型strAge强制
转换为整型变量age*/
if(strAge!=null&&!strAge.equals(""))
age=Integer.parseInt(strAge);
Stringsex=request.getParameter("sex");
Stringdept=request.getParameter("dept");
try{
//下面使用JDBC-ODBC桥与数据库SC建立连接 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn=DriverManager.getConnection("jdbc:odbc:SCdsn","","");
state=conn.createStatement();
/*通过if语句判断如果action的值为insert,则根据前面获取的变量值创建数
据添加的SQL语句*/
if(action.equals("insert")){//数据添加
sql="insertintoStudent(Sno,name,sex,age,department)" +"values('"+no+"','"+name+"','"+sex+"',"
+age+",'"+dept+"')";
}elseif(action.equals("delete")){//数据删除
sql="deletefromStudentwhereSno='"+no+"'";
}elseif(action.equals("update")){//数据修改
sql="updateStudentsetname='"+name+"',sex='"+sex
+"',age="+age+",department='"+dept+"'whereSno='" +no+"'";
}
/*用state的executeUpdate()方法执行sql表示的SQL语句,当用户单击“新
增”按钮时,则实行数据添加的SQL语句*/
state.executeUpdate(sql);
}catch(Exceptione){
e.printStackTrace();
}finally{/*关闭数据库连接和操作用到的两个对象Statement和Connection,并捕捉与
SQL相关的异常*/
try{
if(state!=null)
state.close();
if(conn!=null)
conn.close();
}catch(SQLExceptione){
e.printStackTrace(); }
}
}
//下一条语句将页面重定向到student.jsp,getContextPath方法获取当前站点的根路径
response.sendRedirect(request.getContextPath()+"/student.jsp");
}
//serStudent的撤销方法
publicvoiddestroy(){ super.destroy();//Justputs"destroy"stringinlog
}
}
通过阅读serStudent的源代码和相应的注释可以获知:当用户填写新增学生的数据并单击“新增”按钮后,JSP容器Tomcat执行serStudent的class文件,首先获取action和表单form1中文本框的值,并对获取的age文本框中的值进行数据类型转换;然后与数据库SC建立连接,用if语句判断出action的值为insert,将数据添加语句“insertinto…”赋值给字符串变量sql,接着Statement对象state执行该SQL语句;最后客户端的页面跳转到student.jsp。本书中的URL地址为http://locahost:8080/Chapter11/student.jsp,客户端的浏览器最终显示图11-16所示的页面。
serStudent在web.xml中的配置信息如下:
web.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appversion="2.5"
xmlns="/xml/ns/javaee" xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/xml/ns/javaee
/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>serStudent</servlet-name>
<servlet-class>servlet.serStudent</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>serStudent</servlet-name>
<url-pattern>/servlet/serStudent</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
依据serStudent的url-pattern值,添加数据表单form1属性action的值为“/servlet
/serStudent”,这样才能将新增学生的信息正确提交给serStudent进行处理。
当用户在图11-16所示的页面单击第3行数据后面的“删除”按钮后,Tomcat执行对Student表中学号为200215123数据行(即元组)的删除(delete)操作,同时客户端页面再次返回到student.jsp,对当前的Student表进行查询,结果如图11-20所示。11.4数据删除
图11-20删除学号为200215123学生的数据本实例实现数据删除操作的具体步骤如下:
(1)
sutdent.jsp执行完对Student表的查询,并使用Resultset对象逐行显示查询结果时,在每行数据后面均添加“删除”和“修改”两个按钮,具体代码段如下:
<%
Connectionconn=null;
Statementstate=null;
ResultSetrs=null;
try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn=DriverManager.getConnection("jdbc:odbc:SCdsn","","");
state=conn.createStatement();
Stringsql="select*fromStudent";
rs=state.executeQuery(sql);
intcount=0;
while(rs.next()){ Stringno=rs.getString("Sno");
Stringname=rs.getString("name");
Stringsex=rs.getString("sex");
Stringdept=rs.getString("department");
intage=rs.getInt("age");
%>
<tr>
<!--下面按照行号、学号、姓名、性别、年龄、所在系的顺序分别在表格的单元格中显示每
个学生的信息--> <td><%=++count%></td>
<tdclass="td<%=count%>"><%=no%></td>
<tdclass="td<%=count%>"><%=name%></td>
<tdclass="td<%=count%>"><%=sex%></td>
<tdclass="td<%=count%>"><%=age%></td>
<tdclass="td<%=count%>"><%=dept%></td>
<!--input标签的作用在每行数据后面增加一个“删除”按钮--> <td><inputclass="del"type="button"value="删除"id="del<%=count%>"onclick="javascript:deleteLine(<%=no%>)"/></td>
<!--下面input标签的功能是在“删除”按钮后面再增加一个“修改”按钮-->
<td><inputclass="edit"type="button"value='修改'id="edit<%=count%>"onclick="process(this)"name="<%=count%>"/></td>
</tr>(2)单击“删除”按钮触发的操作。依据“删除”按钮的onclick属性值“javascript:
deleteLine(<%=no%>)”可以知道,在单击“删除”按钮后将调用JavaScript函数deleteLine,并输入当前数据行学生的学号作为函数的参变量。JavaScript函数deleteLine()的代码为:
functiondeleteLine(no){
window.location.href="servlet/serStudent?act=delete&no="+no;
}从具体代码可以看出函数deletLine的功能是让客户端浏览器窗口向相对路径为servlet/serStudent的ServletserStudent发送请求,并传递两个参数act(数据操作类型)和no(学号)。
(3)Tomcat按照路径找到并运行serStudent字节码文件,对学号为no的学生数据进行删除操作,并将客户端URL重定向到student.jsp,以表格的形式显示Student表中的数据,具体操作代码段如下:publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
request.setCharacterEncoding("GBK");
Connectionconn=null;
Statementstate=null;
Stringsql="";
/*下面采用request对象的getParameter()方法获取客户端发送过来的属性act的值,此时为
delete*/ Stringaction=request.getParameter("act");
if(action!=null){
System.out.print(action);
//下面获取客户端发送过来的属性no的值,即要删除的学生的学号
Stringno=request.getParameter("no");
…
try{/*加载JDBC-ODBC桥驱动,与数据库SC建立连接,创建发送SQL语句的对象state*/
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn=DriverManager.getConnection("jdbc:odbc:SCdsn","","");
state=conn.createStatement();
/*通过if语句判断action的值是否为insert,结果为false,直接跳转到下一个elseif语句*/
if(action.equals("insert")){ sql="insertintoStudent(Sno,name,sex,age,department)"
+"values('"+no+"','"+name+"','"+sex+"',"
+age+",'"+dept+"')";
}
/*通过if语句判断action的值是否为delete,结果为true,将“delete…”语句赋值给sql
*/
elseif(action.equals("delete")){
sql="deletefromStudentwhereSno='"+no+"'";}
//通过state的executeUpdate方法执行sql表示的数据删除语句
state.executeUpdate(sql);
…
}catch(Exceptione){
e.printStackTrace();
}finally{
try{
if(state!=null)
state.close();
if(conn!=null)
conn.close();
}catch(SQLExceptione){
e.printStackTrace();
}
}
}//将页面重定向到student.jsp,getContextPath方法获取当前站点的根路径
response.sendRedirect(request.getContextPath()+"/student.jsp");
}
当用户单击图11-20所示的数据表中序号为1的数据后面的“修改”按钮后,页面转变为图11-21所示的样式。即表格中学号为200215121的学生五个属性值均变为文本输入框,并在文本框中预先显示当前该学生的五个属性值,但显示学号的文本框中的值为灰色,用户不能更改,因为学号(Sno)是Student的主码,所以用户只能修改后面四个属性的值。而且该数据行后面的“删除”和“修改”按钮变为“提交”和“取消”按钮,同时其他数据行后面的“删除”和“修改”按钮也不显示。11.5数据更新
图11-21单击修改按钮后的页面样式上述页面样式的变化是通过JavaScript实现的,下面进行详解。
(1)单击“修改”按钮,依据该按钮的onclick属性值,触发JavaScript函数process(obj),代码如下:
<tr>
<td><%=++count%></td>
<tdclass="td<%=count%>"><%=no%></td>
<tdclass="td<%=count%>"><%=name%></td>
<tdclass="td<%=count%>"><%=sex%></td> <tdclass="td<%=count%>"><%=age%></td>
<tdclass="td<%=count%>"><%=dept%></td>
<td><inputclass="del"type="button"value="删除"id="del<%=count%>"onclick="javascript:deleteLine(<%=no%>)"/></td>
<!--在下面的input标签中采用edit和count值结合作为“修改”按钮的id值,规定onclick
事件的触发函数为process(),“修改”按钮的name值为count--> <td><inputclass="edit"type="button"value='修改'id="edit<%=count%>"onclick="process(this)"name="<%=count%>"/></td>
</tr>
从上述代码可以看出每行数据后面的“删除”和“修改”按钮的id和name值均由变量count生成,这样可确保不同数据行中两个按钮的id和name值不同。onclick="process(this)"中向函数process输入的参数this代表“修改”按钮,即当前对象。(2)
process(obj)函数的功能是生成输入修改学生信息的表单,包括“提交”和“取消”两个按钮,同时把原有数据显示在文本输入框中。单击“提交”按钮可以按照用户输入的数据更新Student表中选定学生的信息;单击“取消”按钮后则页面重新变为图11-17所示的样式。由于在process(obj)函数中要调用hideDelEditAndInserInput(obj,n)和dispDelEditAnd
Review()两个JavaScript函数,所以我们先熟悉其具体功能及相应的代码。这两个JavaScript函数存储在名为script.js的文件中。student.jsp通过<script>标签引入该js文件,具体代码如下:
<scripttype="text/javascript"src="js/script.js"></script>。
文件script.js的具体代码如下:
script.jsfunctiongetClass(tagnamei,className){//tagnamei指标签元素,className指class的值
//当浏览器不支持getElementsByClassName的时候用下面的方法
vartagname=document.getElementsByTagName(tagnamei);//获取指定元素
vartagnameAll=[];//这个数组用于存储所有符合条件的元素
for(vari=0;i<tagname.length;i++){//遍历获得的元素 if(tagname[i].className==className){//如果获得的元素中的class的值等于指定的
类名,就赋值给tagnameAll
tagnameAll[tagnameAll.length]=tagname[i];
}
}
returntagnameAll;
}vartdNodes;//表格的某一行根节点
vardelNodes;//所有“删除”按钮根节点
vareditNodes;//所有“修改”按钮根节点
varselectedIndex;//当前选中行的索引值,即student.jsp中选中行的count值,用于定位
vartempData=newArray();//缓存数组
/*window.onload的作用是窗口在“加载”(onload)时获取页面中所有class值为"del"和"edit"的input
元素,即页面中所有的“删除”和“修改”按钮*/
window.onload=function(){
delNodes=getClass("input","del");
editNodes=getClass("input","edit");
};
/*函数hideDelEditAndInserInput()的作用是隐藏所有的“删除”和“修改”按钮,插入有显示值的
文本输入框*/
functionhideDelEditAndInserInput(obj,n){
varcount=delNodes.length; for(vari=0;i<count;i++){//采用循环语句将所有的“删除”和“修改”按钮隐藏
delNodes[i].style.display="none";//隐藏索引为i的“删除”按钮
editNodes[i].style.display="none";//隐藏索引为i的“修改”按钮
}
//插入文本输入框
/*下一行代码的作用是获取所有class值为
"td"+(例如td2)的标签元素<td>,即
要修改的数据行中5个属性值所在的<td>,并存入tdNodes*/
tdNodes=getClass("td","td"+);
//下面用for循环遍历tdNodes中的节点,一次插入一个文本输入框
for(vari=0;i<tdNodes.length;i++){
varnode=document.createElement("input");//创建input元素
="up"+i;//设定input元素的name属性
/*下面的if语句的作用是设置主码不可编辑n=1表示第一个文本输入框不可编辑,n=2
表示前两个文本输入框不可编辑*/
if(i<n)
node.disabled=true;
/*下一条语句将原来表格中被修改行的<td>中的属性值赋给新创建的节点node的
value属性*/
node.value=tdNodes[i].childNodes[0].nodeValue;
node.className="in";
tempData[i]=node.value;//记录到缓存中 tdNodes[i].childNodes[0].nodeValue="";//将<td>中的原始值置为空
tdNodes[i].appendChild(node);//在当前的<td>中添加一个孩子节点node
}
}
/*函数dispDelEditAndReview()的作用是显示前面隐藏的所有“删除”和“修改”按钮,并从
缓存中恢复表格中被修改行的数据*/
functiondispDelEditAndReview(){ varcount=delNodes.length;
for(vari=0;i<count;i++){
delNodes[i].style.display="block";//显示“删除”按钮
editNodes[i].style.display="block";//显示“修改”按钮
}
//恢复原来的表格
for(vari=0;i<tdNodes.length;i++)
{//下一条语句的作用是移除为<td>新增的孩子节点,即文本输入框 td
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【T8联考】2026届高三4月阶段练习(湖北版)化学+答案
- 2025杭州职业技术学院教师招聘考试题目及答案
- 2025汉江师范学院教师招聘考试题目及答案
- 2026年遴选模拟考试难题及答案
- 2026吉林大学白求恩第一医院后勤工作部水暖维修工招聘2人建设笔试备考试题及答案解析
- 2026福建厦门市集美区招商中心选聘4人建设笔试备考试题及答案解析
- 2026甘肃张掖市民乐县城镇公益性岗位招聘42人(第二批)建设笔试模拟试题及答案解析
- 2026北京联合大学招聘45人建设考试参考试题及答案解析
- 2026年芜湖市企业就业见习岗位招募建设考试参考试题及答案解析
- 2026广东深圳市儿童医院招聘4人建设考试备考题库及答案解析
- 水务集团招聘考试笔试试题及答案
- 2025年重庆初级注安考试试题及答案
- 浙江省七彩阳光新高考研究联盟2024-2025学年高二下学期期中联考物理试卷
- 工完料净场地清课件
- 《数字图像与视频处理》课件-第3章 形态学图像处理
- 历年通信工程概预算考试试题与答案
- 职高语文面试题目及答案
- 2024年安徽省高级人民法院岗位招聘笔试真题
- 中共山西省委党校在职研究生考试真题(附答案)
- 2025年广东省中考数学试卷真题(含答案详解)
- 高中生数学建模论文
评论
0/150
提交评论