《Java语言程序设计案例教程》课件第10章_第1页
《Java语言程序设计案例教程》课件第10章_第2页
《Java语言程序设计案例教程》课件第10章_第3页
《Java语言程序设计案例教程》课件第10章_第4页
《Java语言程序设计案例教程》课件第10章_第5页
已阅读5页,还剩167页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第10章JDBC与数据库应用程序开发10.1JDBC的概念与数据库的访问10.2JDBCAPI编程10.3JDBC应用程序综合实例第10章JDBC与数据库应用程序开发

学习目标

理解JDBC的概念,掌握使用JDBC访问数据库的过程;

学会使用JDBC/ODBC桥接驱动程序的方式访问数据库;

了解JDBCAPI中定义的主要接口的功能;

学会简单GUI界面数据库应用程序的开发。在一个信息管理类应用软件的开发中,会使用到很多数据,这些数据大多具有持久性(即需要长期保存),而使用数据库是永久保存数据的最佳选择。那么,在Java程序中如何使用和操作数据库中的数据呢?由Sun公司提供的JDBC是一套基于Java技术的数据库编程接口,它由一些操作数据库的Java类和接口组成。用JDBC编写访问数据库的程序,可以实现应用程序与数据库的无关性,即设计人员不用关心系统具体使用的是什么数据库管理系统,只要数据库厂商提供了该数据库的JDBC驱动程序,就可以在任何一种数据库系统中使用。本章介绍JDBC的概念、工作原理和在Java程序中访问数据库的方法。10.1JDBC的概念与数据库的访问

JDBC提供了在程序中直接访问数据库的功能。那么,什么是JDBC?JDBC是如何工作的?本节将介绍JDBC的这些基本知识。10.1.1使用JDBC访问数据库

1.JDBC的概念

JDBC是一种用于执行SQL语句的JavaAPI。JDBC本身是一个商标名而不是一个缩写字,但JDBC常被人们认为代表“Java数据库连接(JavaDatabaseConnectivity)”的意思。JDBC由一组用Java编程语言编写的类和接口组成,这些类和接口完成与数据库操作有关的各种功能,因此,数据库开发人员可以使用JDBC来编写数据库应用程序。现在,JDBC已经是Java2SDK的一个重要组成部分,JDBC中定义的类和接口都在java.sql包中。JDBCAPI的优点是不必为访问不同的数据库而编写专门的程序。也就是说,为访问Oracle数据库、Informix数据库或SQLServer2000数据库等,只需用JDBCAPI编写一个应用程序就可以了,而且使用Java语言编写的应用程序无需为不同的操作系统平台编写不同的应用程序。因此,将Java技术和JDBC结合起来编写访问数据库的Web应用程序是一种很好的选择。综上所述,JDBC是一种面向对象的、基于Java技术的、用于访问数据库的API,它由一组用Java编程语言编写的类和接口组成,为数据库开发人员和数据库供应商提供了访问数据库的标准。

2. JDBC访问数据库的原理通常,我们所说的数据库访问程序,是指它可以完成以下两种操作:●该程序能够从数据库中读取数据;●该程序可以将程序中的数据写入数据库。在Java程序中,具体访问数据库的过程可以用图10-1表示。图10-1Java程序访问数据库的过程从图10-1可以看出,要使用JDBC技术访问数据库(如进行数据查询)时,Java程序要通过JDBCAPI将数据库操作语句发送给JDBC驱动程序管理器。JDBC驱动程序管理器可以以两种方式与数据库进行通信:一种方式是使用JDBC/ODBC桥接驱动程序间接访问数据库;另一种方式是使用JDBC驱动程序直接访问数据库。

Microsoft公司设计的开放式数据库连接ODBCAPI,是目前广泛应用于Windows平台上访问关系数据库的编程接口。JDBC/ODBC桥接驱动程序就是将以JDBC方式访问数据库的操作转换为以ODBC访问数据库的方式,然后由ODBC驱动程序直接访问数据库。一般情况下,数据库生产厂商提供的JDBC驱动程序可以直接访问数据库,因此这种方式简单、高效,现在很多软件开发者都使用这种方式对数据库进行访问。

3.使用JDBC访问数据库的步骤

Java程序和数据库系统两者之间并没有什么本质的联系,Java程序要访问数据库中的数据,在程序与数据库之间就要建立所谓的“连接”,只有这个“连接”建立以后,才可以访问数据库。具体在一个Java程序中访问数据库的步骤如下:

1)装入JDBC驱动程序在访问数据库前,首先要装入某种类型的JDBC驱动程序。不同厂商的数据库系统,其驱动程序也不同,如IBM公司的DB2数据库,其驱动程序是DB2Driver;微软公司的SQLServer2000数据库,其JDBC/ODBC桥接驱动程序是JdbcOdbcDriver。装入JDBC驱动程序时要使用Class类的forName()方法,forName()方法的参数就是要装入的驱动程序的名称。Class类是java.lang包中定义的一个公共的(public)最终类(final)。Class类的实例表示运行着的Java程序中的类与接口。如要加载Oracle9i数据库的驱动程序,可以使用如下的语句:Class.forName("oracle.jdbc.driver.OracleDriver");要加载MSSQLServer2000数据库的驱动程序,可以使用如下的语句:Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");在调用Class.forName()方法后,会自动创建数据库驱动程序的实例,并向驱动程序的管理器(DriverManager类)进行注册。要注意的是,一般不用显式的方法直接创建驱动程序的实例。在数据库的驱动程序装入后,就可以使用下面介绍的方法连接数据库。

2)建立数据库连接在给数据库装入驱动程序后,可以使用下列语句建立与数据库的连接:Connectionconn=DriverManager.getConnection(URL,"用户名","用户密码");数据库连接用Connection类的一个对象表示,该类的对象使用DriverManager类的getConnecion方法获得。其中:参数URL表示要连接数据库的具体位置;用户名表示登录数据库的用户标识;用户密码表示登录数据库时该用户的密码。执行getConnection方法时,DriverManager类将搜索可以接受URL所代表数据库的驱动程序(DriverManager类存有已注册驱动程序的清单),如果找到合适的驱动程序,就从该驱动程序获取数据库的连接并将它返回给应用程序。如果找不到合适的驱动程序,就无法建立与数据库的连接,Java应用程序便抛出一个SQLException异常。不同的JDBC驱动程序其对应的URL也不同。 JDBCURL提供了一种确认数据库的方法,这样特定的数据库驱动程序就能识别它,并与之建立连接。JDBCURL一般由三部分组成,各部分之间用冒号分隔:jdbc:子协议:子名称各部分的含义是:● jdbc:表示协议,JDBCURL中的协议总是jdbc。●子协议:表示驱动程序名或数据库连接机制名称。●子名称:根据子协议的不同而不同。在实际程序设计中,如果通过ODBC桥接方式连接本地数据库,则URL的格式为jdbc:odbc:数据源名在这种情况下,由于ODBC已经提供了主机、端口等信息,因此可以省略这些信息。如果使用JDBC驱动程序直接和数据库服务器(如SQLServer2000)相连,则URL的格式为jdbc:microsoft:sqlserver://主机地址:1433当访问本机上的数据库时,“主机地址”为“127.0.0.1”,1433是数据库服务器默认的侦听端口号。如果要访问Oracle数据库,则URL的格式为jdbc:oracle:thin:@localhost:1521:数据库实例名

3)执行SQL语句在应用程序与数据库之间建立了连接以后,就可以用这个连接来向数据库传送SQL语句了。从程序中向数据库管理系统发送的SQL语句有如下4种:SELCETINSERTDELETEUPDATE其实,JDBC对发送的SQL语句类型不加任何限制,这为JDBC编程提供了很好的灵活性,但程序员应该保证SQL语句的合法性与完整性。如果发送了DBMS不能识别的SQL语句,则操作就会失败并抛出异常。那么,在建立了数据库连接以后,如何向数据库发送SQL语句呢?

JDBC编程中,在发送一条SQL语句之前,必须创建一个Statement对象,由该对象负责向数据库发送SQL语句。创建一个Statement对象时,要调用Connection接口的createStatement()方法,其一般用法是:Statementstmt=conn.createStatement();在Statement对象创建之后,就可以向数据库发送SQL语句了。如果要向数据库发送查询语句,则可以使用Statement接口的executeQuery()方法。如下面的语句表示查询student表中的记录:ResultSetrs=stmt.executeQuery("SELECT*FROMstudent");

SQL语句执行后的结果返回到ResultSet接口的一个实例中。ResultSet接口是专门用来保存SQL语句查询结果的。在上面的语句中,查询结果保存在rs中。如果要向数据库发送INSERT、UPDATE或DELETE语句,就必须使用Statement接口的executeUpdate()方法。如下面是一条用INSERT插入记录的语句:intnumberOfRows=stmt.executeUpdate("INSERTINTOtableName"+"VALUES('Tom',20)");该操作表示在表tableName中插入一行(即一个记录),表示人名的字符串Tom要用单引号引起来,以区别于其外层的双引号。返回的整数值numberOfRows表示受该操作影响的行数。

4)处理操作结果在使用Statement对象的executeQuery()方法执行数据库查询操作时,查询的结果集放入ResultSet对象中,该对象不但存放查询的结果集,还提供了很多用于操作结果集的方法。在每个结果集ResultSet的对象中,有一个逻辑上的指针,通过对该指针的移动,就可以访问到结果集中的所有数据。在开始访问结果集时,指针总是指向结果集数据的第一条数据,之后可以使用ResultSet对象的next()方法让指针指向下一条记录。当指针指向最后一条记录时,如果再使用next()方法,则该方法的返回值为false,表示已经没有可访问的数据了。当指针指向某条记录时,可以使用ResultSet对象的getXXX()方法取得该数据项内某个字段的值。在这里我们用XXX代表要取出的数据类型,如果要取出的数据类型为整型,则使用getInt方法;为实型,则使用getFloat方法。如下面的程序段可以取出结果集中的第一个字段(为int型)和第二个字段(为Float型)的值:while(rs.next()){System.out.println(rs.getInt(1));System.out.println(rs.getFloat(2));}以上的循环语句就可以将rs结果集中的记录取出,并将第一个字段和第二个字段的值输出。

5)关闭数据库连接在对一个数据库的操作完成以后,为了释放该数据库连接所占用的系统资源,应该关闭Connection、Statement和ResultSet等对象。如要关闭上面创建的与数据库操作有关的对象的程序段为:try{rs.close();stmt.close();conn.close();}catch(SQLExceptione){e.printStackTrace();}

4. java.sql包介绍前面已经提到,JDBCAPI被存入java.sql包中,其中包括访问数据库时所必需的一些类、接口和异常,其中比较重要的类与接口有:● java.sql.DriverManager:该类用于跟踪JDBC驱动程序,其主要功能是使用它的getConnection()方法来取得一个与数据库的连接。● java.sql.Driver:该接口代表JDBC驱动程序。这个接口由数据库厂商实现,如oracle.jdbc.OracleDriver类是Oracle数据库提供的该接口的实现。● java.sql.Connection:该接口代表与数据库的连接,它通过DriverManager.getConnection()方法来获得。该接口提供了创建SQL语句的方法,以完成SQL操作,SQL语句只能在Connection提供的环境内部执行。● java.sql.Statement:该接口提供了在给定数据库连接的环境中执行SQL语句的方法。该接口的子接口java.sql.PreparedStstement可以执行预先解析过的SQL语句;该接口的另外一个子接口java.sql.CallableStatement可以执行数据库的存储过程。● java.sql.ResultSet:这个接口保存了执行数据库的查询语句后所产生的结果集,可以通过它提供的next()或absolute()等方法定位到结果集的某行。● java.sql.SQLException:这是一个异常接口,它提供了对数据库操作错误时的信息。这些接口和类的具体用法在下面介绍。10.1.2【案例10-1】使用JDBC/ODBC桥接驱动程序访问数据库

1.案例描述在SQLServer2000中有一个存放学生信息的数据库students,在students数据库中有一个存放计算机系学生信息的数据表,表名为“JSJXstuInfo”,该表的字段描述如表10-1所示。编写一个Java程序,读取“JSJXstuInfo”表中的数据,并将数据显示出来。表10-1表JSJXstuInfo中的字段及数据类型

2.案例效果案例程序的执行效果如图10-2所示。图10-2案例10-1的显示效果

3.技术分析使用JDBC-ODBC桥接驱动程序访问数据库时,首先要在Windows操作系统下建立DSN数据源。DSN指数据源名(DataSourceNames),由于它把数据库、数据库的驱动程序和一些可选设置联系起来,用一个名称表示,因此在配置好DSN以后访问数据库就比较简单了。

DSN的配置方法如下:

1)启动创建数据源的窗口在“控制面板”下找到“性能和维护”,然后打开“管理工具”窗口,在“管理工具”窗口中打开“数据源(ODBC)”。打开后的窗口名为“ODBC数据源管理器”,如图10-3所示。图10-3“ODBC数据源管理器”窗口

2)创建一个新数据源在图10-3所示的窗口中选择“用户DSN”选项卡(注意在配置数据库服务器时,要选择“系统DSN”选项卡),然后单击“添加”命令按钮,显示如图10-4所示的“创建新数据源”窗口。在图10-4所示的窗口中选择“SQLServer”,然后单击“完成”按钮,则显示如图10-5所示的“建立新的数据源到SQLServer”窗口。图10-4“创建新数据源”窗口图10-5“建立新的数据源到SQLServer”窗口在图10-5所示窗口的“名称”文本框中输入“students”(表示数据库的名称),在“服务器”下拉列表框中选择“(local)”,然后单击“下一步”按钮,显示如图10-6所示的窗口。在图10-6所示的窗口中可以选择默认设置方式,然后单击“下一步”按钮,显示如图10-7所示的窗口。图10-6用户身份验证窗口图10-7选择默认数据库窗口在图10-7所示的窗口中,将“更改默认的数据库为”选中,然后在下拉列表框中选择“students”数据库。单击“下一步”按钮,显示如图10-8所示的窗口。在图10-8所示的窗口中根据需要选中有关选项后,单击“完成”按钮,显示如图10-9所示的窗口。图10-8数据库选项窗口图10-9数据源配置结果窗口图10-9所示的窗口显示新建数据源的配置信息。为了测试数据源的配置是否成功,可以单击图10-9中的“测试数据源”按钮,如果显示如图10-10所示的窗口,则说明创建数据源的客户端可以与数据库服务器建立连接。单击“确定”按钮,完成配置过程。在数据源配置完成后,就可以使用本节介绍的访问数据库的步骤编写程序和调试程序了。在数据源配置完成后,就可以使用本节介绍的访问数据库的步骤编写程序和调试程序了。图10-10数据源测试结果窗口

4.程序解析下面是该案例的程序代码:01//**************************************02//案例:10-1程序名:Select.java03//功能:使用JDBC技术将数据库中的数据读出04//**************************************0506importjava.sql.*;07importjava.io.*;08classSelect{ 09 publicstaticvoidmain(String[]args){ 10 try {11 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");12 Connectionconn=DriverManager.getConnection

("jdbc:odbc:students");13 Statementstmt=conn.createStatement();14 StringstrQuery="SELECT*FROMJSJXstuInfo";15 ResultSetrs=stmt.executeQuery(strQuery);16 while(rs.next()){17

System.out.print(rs.getString("stuNo"));18 System.out.print(rs.getString("stuName"));19 System.out.print(""+rs.getInt("stuAge"));20 System.out.print(""+rs.getString("stuSex"));21 System.out.println(""+rs.getString("stuClass"));22 }23 rs.close();24 stmt.close();25 conn.close();26 }27 catch(Exceptione){28 System.out.print(e);}29 }30}该案例比较简单,它是根据本节介绍的编写访问数据库程序的步骤完成的。要注意的是,访问数据库的程序由于数据库或数据表可能不存在或与数据库的连接不能正确建立等因素,往往会产生异常。因此,访问数据库的代码要放入异常处理语句块try中,并要在catch语句块中进行异常处理。10.1.3【相关知识】使用JDBC修改数据表除了对数据表可以进行查询(select)操作外,还可以使用JDBC给数据表插入记录(insert)、删除记录(delete)和修改记录(update)。

1.在数据表中插入记录下面的程序将在学生信息表JSJXstuInfo中插入一条记录。01importjava.sql.*;02importjava.io.*;03classInsert04{05 publicstaticvoidmain(String[]args)06 { 07 try 08 { 09 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");10 Connectionconn=DriverManager.getConnection("jdbc:odbc:students");11 Statementstmt=conn.createStatement(); 12 StringstrInsert="INSERTINTOJSJXstuInfo

VALUES('0010','任高','18','男','JSJ002')";13 introws=stmt.executeUpdate(strInsert);14 System.out.println(“在数据库表中插入了”+rows+“行记录");15 stmt.close();16 conn.close();17 }18 catch(Exceptione){System.out.print(e);}19 }20}在该实例中,第12行定义了要插入记录的SQL语句,第13行使用executeUpdate方法执行SQL插入语句,第14行显示插入的记录行数。

2.删除数据表中的记录如果将上面程序中的12、13、14行换为以下的语句,则将满足条件的学生记录从JSJXstuInfo表中删除。12

StringstrDelete="DELETEFROMJSJXstuInfo

WHEREstuAge=19"; 13

introws=stmt.executeUpdate(strDelete);14

System.out.println("在数据库表中删除了"+rows+“行记录");第12行定义了删除记录的SQL语句,第13行使用executeUpdate方法执行SQL语句,第14行显示删除的行数。

3.修改数据表中的记录如果将上面程序中的第12、13、14行换为以下的语句,则将JSJXstuInfo表中满足条件的学生记录进行修改:12 StringstrUpdate="UPDATEJSJXstuInfoSET

stuAge=stuAge+1"; 13 introws=stmt.executeUpdate(strUpdate);14 System.out.println("数据库表中的"+rows+“行被修改了");第12行定义了一个修改学生记录的SQL语句,该语句将JSJXstuInfo表中所有学生记录的stuAge字段加1(即所有学生的年龄增加1)。由以上程序可以看出,如要修改数据表中的记录,则需使用Statement的executeUpdate方法。10.2JDBCAPI编程上一节介绍了4种对数据表进行操作的JDBC程序,在程序中已经使用了JDBCAPI。在对JDBCAPI有了初步了解以后,本节我们将较为详细地介绍JDBCAPI提供的数据库编程功能。10.2.1Connection接口

java.sql.Connection接口用来建立与数据库的连接,该接口的实例通过DriverManager.getConnection()方法来获得。Connection接口提供了进行事务处理、创建SQL语句等操作的方法。SQL语句只能在Connection提供的环境内部执行。该接口提供的常用方法有:● StatementcreateStatement():创建执行SQL语句的Statement对象。● PreparedStatementprepareStatement(Stringsql):创建可以执行预编译SQL语句的PreparedStatement对象。● CallableStatementprepareCall(String):通过创建一个CallableStatement对象来执行一个SQL存储过程调用语句。● voidsetAutoCommit(BooleanAutoCommit):如果参数为true,则启动自动提交功能;否则,禁止自动提交。● DatabaseMetaDatagetMetaData():返回用于确定数据库特性的DatabaseMetaData对象。● voidcommit():提交对数据库的操作。● voidrollback():回退(即撤消)对数据库的操作。● voidclose():释放对数据库的连接。10.2.2Statement接口

Java程序与数据库的建立连接以后,就可以使用Statement接口的对象执行SQL语言了。Statement接口不能直接实例化一个对象,该接口的实例只能由Connection对象的createStatement()方法产生。该接口提供的常用方法有:● ResultSetexecuteQuery(Stringsql):执行一条SQL查询语句,返回的结果保存在ResultSet对象中。● intexecuteUpdate(Stringsql):执行一条INSERT、UPDATE或DELETE语句,返回的结果为受SQL语句影响的行数。另外,它也可以执行没有返回值的SQL语句,如SQL创建数据表的语句,这时返回的值为0。● voidsetMaxRows(intmaxmaxRows):用来限制ResultSet可包含的最大行数。如果超过这个限制,则超过的行将被丢弃。● voidgetMaxRows():返回记录集中当前包含的最大行数。下面的实例使用executeUpdate(Stringsql)方法创建一个名为JSJXstuScore的数据表。该表有两个字段:“stuNo”字段,用来存储学号;“java”字段,用来存储该学生的成绩。01importjava.sql.*;02importjava.io.*;03classCreateTable{ 04 publicstaticvoidmain(String[]args){ 05 try {06 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");07 Connectionconn=DriverManager.getConnection

("jdbc:odbc:students");08 Statementstmt=conn.createStatement();09 StringstrCreate="CREATETABLEJSJXstuScore

(stuNochar(6),javaint)"; 10 stmt.executeUpdate(strCreate);11 System.out.println("创建了一个数据库表"); 12 stmt.close();13 conn.close();14 }15 catch(Exceptione){System.out.print(e);} 16}17}该实例的09行定义了一条创建数据表的SQL语句,第10行调用Statement对象的executeUpdate方法执行该语句。该程序正确执行后,将在Students数据库中创建一个名为JSJXstuScore的数据表。10.2.3PreparedStatement接口如果一条SQL语句需要被执行多次,则当使用Statement对象时,每次都要将该SQL语句传递给数据库管理系统DBMS,这会严重影响SQL语句的执行效率。为此,可以使用Statement接口的子接口PreparedStatement,它的实例包含了已编译的SQL语句。已编译的SQL语句是指当一条SQL语句传到DBMS时,由DBMS对SQL语句进行编译和优化,并将编译后的SQL语句保存在缓存中。这样以后执行该语句时,可以从缓存中直接取出该SQL语句进行执行,提高了SQL语句执行的效率。包含于PreparedStatement对象中的SQL语句可有一个或多个参数,因为参数用于提供数据(即输入),所以称为IN参数(即输入参数)。IN参数的值在SQL语句创建时未被指定,该语句为每个IN参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX方法来提供。作为Statement的子接口,PreparedStatement继承了Statement的所有功能。另外,它还添加了一整套方法,这些方法用于设置发送给数据库以取代SQL语句中IN参数占位符的值。同时,PreparedStatement接口提供的方法executeQuery和executeUpdate不再需要参数。

1.创建PreparedStatement对象同Statement对象类似,PreparedStatement对象只能使用Connection对象的prepareStatement方法获得。下面的语句(其中conn属于Connection类型)创建了一个PreparedStatement对象,该对象是含有两个IN参数占位符的SQL语句:PreparedStatementpstmt=conn.prepareStatement("INSERTINTOJSJXstuScoreVALUES(?,?)");

pstmt对象包含的INSERT语句中有两个参数,要求在执行时给这两个参数提供数值,即为IN参数提供具体的数据。

2.设置IN参数的值在执行PreparedStatement对象之前,必须设置每个“?”参数的值。这可通过调用PreparedStatement对象的setXXX方法来完成,其中XXX代表与该参数类型相匹配的数据类型。例如,如果参数是Java中的long类型,则使用的方法就是setLong。setXXX方法的第一个参数是要设置的参数的序数位置,第二个参数设置该参数的值。例如,以下代码将第一个参数设为"00023",第二个参数设置为89:pstmt.setString(1,"00023");pstmt.setInt(2,89);一旦设置了给定语句的IN参数值,就可多次执行该语句,直到调用PreparedStatement对象的clearParameters方法清除参数值为止。下面是一个PreparedStatement对象执行SQL语句的实例程序,该程序使用PreparedStatement对象在数据表JSJXstuScore中插入10条记录。01importjava.sql.*;02importjava.io.*;03classPreparedInsert{ 04 publicstaticvoidmain(String[]args){05 int[]score={67,78,45,78,67,98,97,77,67,87};06 introwCount;07 try {08 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");09 Connectionconn=DriverManager.getConnection

("jdbc:odbc:students");10 StringstrInsert="INSERTINTOJSJXstuScore

VALUES(?,?)";11 PreparedStatementpstmt=conn.prepareStatement

(strInsert);12 for(inti=0;i<10;i++){13 pstmt.setString(1,String.valueOf(i));14 pstmt.setInt(2,score[i]);15 rowCount=pstmt.executeUpdate();16 }17 pstmt.close();18 conn.close();19 }20 catch(Exceptione){System.out.print(e);}21 }22}该实例的05行定义了一个存放学生成绩的数组。10行定义了一条插入记录的SQL语句。11行调用Connection对象的prepareStatement()方法生成一个PreparedStatement的实例。12~16行利用循环语句在数据表JSJXstuScore中插入10条记录。13行调用PreparedStatement的setString方法给JSJXstuScore表的第一个字段设置一个字符串值,其中的String.valueOf函数可以将一个整数转化为字符串。14行调用PreparedStatement的setInt方法给JSJXstuScore表的第二个字段设置成绩,成绩存放在score数组中。10.2.4CallableStatement接口

CallableStatement接口是PreparedStatement接口的子接口,因此它具有Statement接口和PreparedStatement接口所提供的功能。该接口的实例对象为所有的DBMS提供了一种以标准形式调用储存过程的方法。在JDBC中,调用储存过程的语法如下:{call过程名[(?,?,...)]}当储存过程返回一个结果参数时,使用如下的格式:{?=call过程名[(?,?,...)]}一个不带参数、不返回结果的储存过程,可以使用如下的格式调用:{call过程名}注意:方括号表示其中的内容是可选项,方括号本身并不是语法的组成部分。

1.创建CallableStatement对象储存过程保存在数据库中,通过CallableStatement对象就可以调用一个储存过程。因为CallableStatement是一个接口,所以不能直接实例化一个该类的对象。CallableStatement实例对象要使用Connection对象的prepareCall(Stringsql)方法取得。如一个储存过程名为getTestData,它有两个参数,可以使用如下的格式生成CallableStatement对象:CallableStatementcstmt=conn.prepareCall("{callgetTestData(?,?)}");其中,?为占位符。?代表的参数可能是输入参数(IN),也可能是输出参数(OUT),还有可能既是输入参数又是输出参数(INOUT),这取决于储存过程getTestData。通常,创建CallableStatement对象时应当知道所用的DBMS是否支持储存过程。如果需要检查DBMS是否支持储存过程,则可以使用DatabaseMetaData对象的supportsStoredProcedures方法进行测试,如果其返回值为true,则表示该DBMS支持储存过程。

2. IN和OUT参数将IN参数传给CallableStatement对象是通过setXXX方法完成的。该方法继承自PreparedStatement接口,所传入参数的类型决定了所用的setXXX方法(例如,用setFloat来传入float值等)。如果储存过程返回OUT参数,则在执行CallableStatement对象以前必须先注册每个OUT参数的JDBC类型(这是必需的,因为某些DBMS要求知道JDBC类型)。注册JDBC类型是用registerOutParameter方法来完成的。在语句执行完后,可以使用CallableStatement的getXXX方法取回参数值。registerOutParameter使用的是JDBC类型(因此它与数据库返回的JDBC类型匹配),而getXXX可将之转换为Java类型。下面是一个使用输出参数的实例:CallableStatementcstmt=conn.prepareCall("{callgetTestData(?,?)}");cstmt.registerOutParameter(1,java.sql.Types.TINYINT);cstmt.registerOutParameter(2,java.sql.Types.DECIMAL,3);cstmt.executeQuery();bytex=cstmt.getByte(1);java.math.BigDecimaln=cstmt.getBigDecimal(2,3);第2行和第3行代码先注册了OUT参数的类型。注意,注册的是JDBC中的数据类型。第4行执行由cstmt所调用的储存过程,第5行和第6行取得在OUT参数中返回的值。方法getByte从第一个OUT参数中取出一个Java字节型数据,而getBigDecimal从第二个OUT参数中取出一个BigDecimal对象(小数点后面带三位数)。

3. INOUT参数既支持输入又支持输出的参数即为INOUT参数。INOUT参数除了要调用registerOutParameter方法外,还要求调用适当的setXXX方法(该方法是从PreparedStatement继承来的)。 setXXX方法将参数值设置为输入参数, 而registerOutParameter方法将它的JDBC类型注册为输出参数。setXXX方法提供一个Java值,而驱动程序先把这个值转换为JDBC值,然后将它送到数据库中。这种IN值的JDBC类型和提供给registerOutParameter方法的JDBC类型应该相同。要检索输出值,就要用对应的getXXX方法。例如,Java的类型为byte的参数应该使用方法setByte来赋输入值。而应该给registerOutParameter方法提供的类型为TINYINT(JDBC类型),同时应使用getByte来取得输出值。下面是一个使用输入/输出参数(INOUT)的实例:CallableStatementcstmt=conn.prepareCall("{callreviseTotal(?)}");cstmt.setByte(1,25);cstmt.registerOutParameter(1,java.sql.Types.TINYINT);cstmt.executeUpdate();bytex=cstmt.getByte(1);上面的代码中,要调用的存储过程名为reviseTotal,它只有一个参数,该参数是INOUT参数。第2行的setByte方法把此参数的输入值设为25,驱动程序将把它作为JDBCTINYINT类型送到数据库中。第3行的注册语句registerOutParameter将该参数注册为JDBCTINYINT类型。第4行执行完该储存过程后,将返回一个新的JDBCTINYINT值。第5行的方法getByte将把这个新值作为Javabyte类型取得后存入变量x中。10.2.5ResultSet接口

ResultSet接口包含符合查询条件的记录的结果集。这个结果集可以看成是一个二维表格,它由若干行组成,其中有查询所返回的列标题及相应的值。通过一套getXXX方法就可以访问当前行中不同列的值。要访问结果集中的数据,首先要找到数据所在的行,然后才能取得该行某列的数据。完成这样的操作要依靠一个指向当前行的指针。在开始时,指针指向第一行之前的位置,调用ResultSet的next方法可将指针移动到结果集的下一行,使下一行成为当前行。如果指针被移到了结果集的最后一行的下面,则next方法返回false。具体应用见案例10-1。对于取得列数据的getXXX方法,JDBC驱动程序试图将基本数据转换成指定的Java类型,然后返回适合的Java值。例如,如果getXXX方法为getString,而基本数据库中的数据类型为VARCHAR,则JDBC驱动程序将把VARCHAR类型转换成Java中的String类型,这样,getString的返回值将为Java中的String对象。

ResultSet中返回Java对象的getXXX方法有getString、getDate、getTime、getTimestamp、getObject等。ResultSet中返回数值的getXXX方法有getByte、getShort、getInt、getLong、getFloat和getDouble。ResultSet中返回布尔值的方法是getBoolean。

getXXX方法返回的Java数据类型与SQL类型的对应关系如表10-2。表10-2Java数据类型与SQL类型的对应关系10.2.6ResultSetMetaData接口

ResultSetMetaData对象可用于查找ResultSet结果集中列的类型和特性。在编程时,ResultSetMetaData对象使用ResultSet对象的getMetaData()方法来取得。例如:ResultSetrs=stmt.executeQuery("SELECTa,b,cFROMTABLE2");ResultSetMetaDatarsmd=rs.getMetaData();intnumberOfColumns=rsmd.getColumnCount();…

ResultSetMetaData接口提供的常用方法如下:● intgetColumnCount():获得ResultSet中的列数。● booleanisCaseSensitive(intcolumn):列是否区分大小写。● booleanisSearchable(intcolumn):该列能否用于WHERE子句。● intisNullable(intcolumn):在该列中是否可以放一个NULL值。● StringgetColumnLabel(intcolumn):获得用于打印输出和显示的建议列标题。● StringgetColumnName(intcolumn):获得列名。● intgetScale(intcolumn):获得一个列的十进制小数点右面数字的位数。● StringgetTableName(intcolumn):获得列的表名。● StringgetCatalogName(intcolumn):获得列所在表的目录名。● intgetColumnType(intcolumn):获得一个列的SQL类型。● booleanisReadOnly(intcolumn):列是否是只读的。技能拓展10.3JDBC应用程序综合实例在各种管理程序中,数据一般都保存在数据库中,应用程序一般使用图形用户界面对数据库中的数据进行修改、插入和删除等。本节以一个实例说明这类程序的设计方法。10.3.1实例描述设计一个管理学生信息的程序,可以对学生信息进行浏览、修改、删除和插入操作。学生的信息由学号、姓名、性别、出生日期、系别、专业、班级和个人简历组成。在SQLServer2000下建立一个学生(students)数据库,在该数据库中建立一个如表10-3所示的学生信息表。表10-3学生信息表10.3.2程序运行结果该程序的运行结果如图10-11所示。图10-11(a)是学生的“个人信息”选项卡,图10-11(b)是学生的“个人简历”选项卡。该程序界面的上部有4个工具按钮:“修改”、“删除”、“添加”和“退出”。在窗口的下部有4个浏览按钮,用来选择窗口中显示的学生记录:第一个按钮表示显示“第一条学生记录”,第二个按钮表示显示当前学生记录的“前一条学生记录”,第三个按钮表示显示当前记录的“后一条学生记录”,第四个按钮表示显示“最后一条学生记录”。图10-11学生信息管理程序运行结果(a)图10-11学生信息管理程序运行结果(b)10.3.3程序设计

1.定义学生类该程序要对学生信息进行处理,所以在程序中要定义一个学生类。学生类的定义如下:01//********************************************02//案例:10-2程序名:Student.java03//功能:定义学生类04//********************************************05packagestudents;0607publicclassStudent{08 privateStringstuNo;//学号09 privateStringstuName;//姓名10 privateStringstuSex;//性别11 privateStringstuBirthday;//出生日期12 privateStringstuDepartment;//系别13 privateStringstuSpeciality;//专业14 privateStringstuClass;//班级15 privateStringstuHistory;//简历16 17 //无参构造方法18 publicStudent(){}19 20 publicStringgetStuNo(){returnstuNo;}21 publicvoidsetStuNo(StringstuNo){22 this.stuNo=stuNo;23 }24 25 publicStringgetStuName(){returnstuName;}26 publicvoidsetStuName(StringstuName){27 this.stuName=stuName;28 }29 30 publicStringgetStuSex(){returnstuSex;}31 publicvoidsetStuSex(StringstuSex){32 this.stuSex=stuSex;33 }34 35 publicStringgetStuBirthday(){returnstuBirthday;}36 publicvoidsetStuBirthday(StringstuBirthday){37 this.stuBirthday=stuBirthday;38 }39 40 publicStringgetStuDepartment(){returnstuDepartment;}41 publicvoidsetStuDepartment(StringstuDepartment){42 this.stuDepartment=stuDepartment;43 }44 45 publicStringgetStuSpeciality(){returnstuSpeciality;}46 publicvoidsetStuSpeciality(StringstuSpeciality){47 this.stuSpeciality=stuSpeciality;48 }49 50 publicStringgetStuClass(){returnstuClass;}51 publicvoidsetStuClass(StringstuClass){52 this.stuClass=stuClass;53 }54 55 publicStringgetStuHistory(){returnstuHistory;}56 publicvoidsetStuHistory(StringstuHistory){57 this.stuHistory=stuHistory;58 }59}学生类的每个属性定义了一个设置属性的方法(setXxx)和一个获取学生属性的方法(getXxx)。第05行表明将定义的学生类放入students包中。用下列命令编译该类:javac-dStudent.java

2.定义从数据库中读取学生记录的类在GUI界面中要显示、修改、插入和删除学生记录,因此,程序中专门定义了一个存取学生信息的类,该类中定义了一些处理学生记录的静态方法。程序如下:001//**********************************************002//案例:10-2程序名:StudentDBA.java003//功能:定义存取数据库的类004//**********************************************005006packagestudents;007008importjava.sql.*;009importjava.util.ArrayList;010importjavax.swing.*;011012publicclassStudentDBA{013 014 privatestaticArrayListstudents=newArrayList();

//存放读取的学生记录015 privatestaticConnectionconn=null;016 privatestaticStatementstatement=null;017 privatestaticResultSetrs=null;018 privatestaticintloc=0;019 020 privatestaticvoidgetDBConnection(){021 try{022 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");023 Connectionconn=DriverManager.getConnection

("jdbc:odbc:students");024 }025 catch(ClassNotFoundExceptione1){

JOptionPane.showMessageDialog(null,“找不到数据库驱动程序类!\n”+e1,“提示”,

JOptionPane.ERROR_MESSAGE);027 }028 catch(SQLExceptione2){029 JOptionPane.showMessageDialog(null,“无法连接数据库!\n"+e2,"提示",JOptionPane.

ERROR_MESSAGE);030 }031 }032 033 publicstaticArrayListgetAllStudents(){034 StringstrSQL="SELECT*FROMStudent";035 students.clear();036 try{037 getDBConnection();038 statement=conn.createStatement();039 rs=statement.executeQuery(strSQL);040 while(rs.next()){041 Studentstu=newStudent();042 stu.setStuNo(rs.getString(1));043 stu.setStuName(rs.getString(2));044 stu.setStuSex(rs.getString(3));045 stu.setStuBirthday(String.valueOf(rs.getDate(4)));046 stu.setStuDepartment(rs.getString(5));047 stu.setStuSpeciality(rs.getString(6));048 stu.setStuClass(rs.getString(7));049 stu.setStuHistory(rs.getString(8));050 students.add(stu);051 }052 }053 catch(SQLExceptione){054 JOptionPane.showMessageDialog

(null,"无法连接数据库!\n"+e,"提示",

JoptionPane.ERROR_MESSAGE);055 }056 finally{057 close();058 }059 returnstudents;060 }061 062 publicstaticStudentgetCurrentStudent(){063 if(students.size()>0)064 return(Student)students.get(loc);065 elsereturnnull;066 }067 068 publicstaticStudentgetNextStudent(){loc++;070 if(loc<students.size())071 return(Student)students.get(loc);072 else{073 loc--;074 return(Student)students.get(loc);}076 }077 078 publicstaticStudentgetPrevStudent(){079 loc--;080 if(loc>=0)081 return(Student)students.get(loc);082 else{083 loc++;084 return(Student)students.get(loc);085 }086 }087 088 publicstaticStudentgetFirstStudent(){089 Students=newStudent();090 if(students.size()>0){091 loc=0;092 s=(Student)students.get(loc);093 }094 returns;095 }096 097 publicstaticStudentgetLastStudent(){098 if(students.size()>0){099 loc=students.size()-1;100 return(Student)students.get(loc);101 }102 else returnnull;103}104105publicstaticvoidaddStudent(Students){106 StringstrSQL="INSERTINTOstudentVALUES(";107 strSQL+="'"+s.getStuNo()+"'"+",";108 strSQL+="'"+s.getStuName()+"'"+",";109 strSQL+="'"+s.getStuSex()+"'"+",";110 strSQL+="'"+s.getStuBirthday()+"'"+",";111 strSQL+="'"+s.getStuDepartment()+"'"+",";112 strSQL+="'"+s.getStuSpeciality()+"'"+",";113 strSQL+="'"+s.getStuClass()+"'"+",";114 strSQL+="'"+s.getStuHistory()+"'"+")";115 try{116 getDBConnection();117 statement=conn.createStatement();118 statement.executeUpdate(strSQL);119 loc=students.size()-1;120 JOptionPane.showMessageDialog

(null,"记录被正确插入!");121 122 }123 catch(SQLExceptione){124 JOptionPane.showMessageDialog(null,“插入数据发生错误!\n”+e,“错误”,

JOptionPane.ERROR_MESSAGE);125 }126 finally{127 close();128 }129}130 131publicstaticvoiddeleteStudent(){132 Students=getCurrentStudent();133 StringstrSQL="DELETEFROMstudentWHERE

stuNo='"+s.getStuNo()+"'";134 try{135 getDBConnection();136 statement=conn.createStatement();137 intn=statement.executeUpdate(strSQL);138 JOptionPane.showMessageDialog(null,n+“行被删除!

");139 if(loc>0)140 loc--;141 }142 catch(SQLExceptione){143 JOptionPane.showMessageDialog(null,“数据删除发生错误!\n“+e,”错误“,JOptionPane.

ERROR_MESSAGE);144 }145 finally{146 close();147 }148}149150publicstaticvoidupdateStudent(Students){151 StringstrSQL="UPDATEstudentSET";152 strSQL+="stuName="+"'"+s.getStuName()+"',";153 strSQL+="stuSex="+"'"+s.getStuSex()+"'

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论