资源描述
第第9章章Java数据数据库技技术9.1 JDBC概述概述 JDBC(Java Database Connection,Java数据库连接)是一种用于执行SQL语句的JavaAPI(应用程序设计接口),它由一些Java语言写的类和界面组成。JDBC提供了一种标准的应用程序设计接口,使得开发人员使用Java语言开发完整的数据库应用程序变得极为简单。通过JDBC,开发人员几乎可以将SQL语句传递给任何一种数据库,而无需为各种数据库编写单独的访问程序。JDBC可以自动将SQL语句传递给相应的数据库管理系统。JDBC扩展了Java的功能,例如在Applet中应用JDBC,可以实现与远程数据库的连接,实现不同平台数据库之间的对话。简单地说,JDBC完成下面三个操作:(1)与一个数据库建立连接。Connection con=DriverManager.getConnection(jdbc:odbc:CallCenter,sa,);(2)向数据库发送SQL语句。stmt=con.createStatement();rs=stmt.executeQuery(SELECT CID,CPin from tCustomer WHERE CID=z1);(3)处理数据库返回的结果。while(rs.next()String theInt=rs.getString(CID);String str=rs.getString(CPin);.9.2 使使 用用JDBC JDBC的接口分为两个层次:一个是面向程序开发人员的JDBC API;另外一个是底层的JDBC Driver API。JDBC API 被描述成为一组抽象的Java接口,应用程序可以对某个数据库打开连接,执行SQL语句并且处理结果。最重要的接口如下:java.sql.DriverManager:处理驱动的调入并且对产生新的数据库连接提供支持。java.sql.Connection:代表对特定数据库的连接。java.sql.Statement:代表一个特定的容器,以对一个特定的数据库执行SQL语句。java.sql.ResultSet:控制对一个特定语句的行数据的存取。其中java.sql.Statement又有两个子类型:(1)java.sql.PreparedStatement:用于执行预编译的SQL语句。(2)java.sql.CallableStatement:用于执行对一个数据库内嵌过程的调用。JDBC Driver API是指java.sql.Driver接口,封装了不同数据库的驱动程序(像Access、Foxpro、SQL Server等)。由于它是数据库底层处理,所以必须提供对java.sql.Connection、java.sql.Statement、java.sql.PreparedStatement和java.sql.ResultSet的实现。如果目标DBMS提供有OUT参数的内嵌过程,那么还必须提供java.sql.CallableStatement 接口。在java.sql.Driver接口中每个数据库驱动程序必须提供一个类,使得系统可以由 java.sql.DriverManager来管理。一个比较好用的驱动程序是在ODBC之上提供对JDBC的实现,从而提供与ODBC接口的JDBC-ODBC 桥。所谓JDBC-ODBC桥,是一个JDBC驱动程序,通过将JDBC操作转换为ODBC操作来实现JDBC操作。它由sun.jdbc.odbc包实现,包含一个用来访问ODBC的本地库,对所有ODBC可用的数据库实现JDBC。通过ODBC子协议,可以使用下面一行代码进行显示加载。Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);加载时,ODBC驱动程序将创建自己的实例,同时在JDBC驱动程序管理器中进行注册。由于JDBC放在ODBC之后,所以实现起来简单且高效。9.2.1 Driver Driver接口是每个驱动器类都需要完成的。JavaSQL框架允许有多个数据库驱动器,每个驱动器应该提供一个类来实现驱动器接口,而驱动器的装载通过DriverManager实例实现。DriverManager将装载尽量多的驱动器,对每个给定的连接请求,将所有的驱动器依次连接到目标数据库上。当驱动器类装载后,Driver应该创建一个实例,然后注册到DriverManager上。9.2.2 DriverManager DriverManager管理一系列JDBC驱动器的基本服务。应用程序可以显式加载JDBC驱动器。例如下面代码显式加载my.sql.Driver。Class.forName(my.sql.Driver);显式加载JDBC-ODBC桥:Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);它的较为重要的方法有:public static Connection getConnection(String url)throws SQLException public static Connection getConnection(String url,Properties info)throws SQLException public static Connection getConnection(String url,String user,String password)throws SQLException 这些方法的功能都是建立一个到给定数据库url的连接。DriverManager试图从注册的JDBC驱动器序列中选择合适的驱动器,返回到url的连接。其中:(1)url为数据库url,格式为 jdbc:subprotocol:subname。(2)info以“标记/数值对”作为连接参数,至少应该包括user和password属性对。(3)user指数据库用户(连接以什么身份建立)。(4)password 是用户的密码。例如:使用JDBC-ODBC桥建立到ODBC配置的数据库CallCenter的连接,访问CallCenter数据库的用户名为sa,密码无。语句行如下:Connection con=DriverManager.getConnection(jdbc:odbc:CallCenter,sa,);9.2.3 Connection 一个Connection(连接)就是一个与特定数据库的会话。在连接的上下文环境中才可以执行SQL语句和返回结果。Connection对象的数据库可以提供描述它的表、SQL语法和存储过程等的信息。它较为重要的方法有:public Statement createStatement()throws SQLException 创建一个Statement对象,用于发送SQL语句到数据库。没有参数的SQL语句通常使用Statement对象执行。如果希望多次执行,使用PreparedStatement更为高效。public PreparedStatement prepareStatement(String sql)throws SQLException 创建一个PreparedStatement对象,发送参数化SQL语句sql到数据库。SQL语句可以预先编译并存储到PreparedStatement语句中。这个对象可以用来高效地多次执行语句。其中:参数sql是包含多个“?”参数的SQL语句,“?”表示输入参数由用户进行设置。例如:创建Statement对象语句如下:stmt=con.createStatement();创建PreparedStatement对象语句如下:pstmt=con.prepareStatement(UPDATE Xuesheng SET 班级=?WHERE 班级=?);9.2.4 Statement Statement对象用于执行一个静态的SQL语句并返回它产生的结果。在缺省情况下,任一时刻每个Statement对象只产生一个ResultSet集。对数据库希望有不同操作得到结果集时,需要创建不同的Statement对象。它的较为重要的方法有:public ResultSet executeQuery(String sql)throws SQLException 执行给定的sql语句,返回一个ResultSet对象。public int executeUpdate(String sql)throws SQLException 执行给定的sql语句,可以是插入(INSERT)、更新(UPDATE)或者删除(DELETE)等,也可以是一个空语句,执行DDL语句。返回值是操作的记录个数。public ResultSet getResultSet()throws SQLException 以ResultSet对象格式返回当前结果集,每个结果集只调用一次。例如:从表tCustomer中返回CID为z1的记录的CID(客户ID)和CPin(密码)列,语句行为:rs=stmt.executeQuery(SELECT CID,CPin from tCustomer WHERE CID=z1);9.2.5 PreparedStatement PreparedStatement代表预编译的SQL语句的对象。一个SQL语句预编译后存储到PreparedStatement对象中,这个对象用来多次执行语句。PreparedStatement继承于Statement,扩展了Statement的用途,提高了Statement的执行效率。它与Statement对象有两点不同:(1)同一个对象可以多次使用。(2)它的SQL语句可以带输入(IN)参数。PreparedStatement在程序语句中的输入参数使用占位符“?”来实现。必须使用类提供的设置方法设置语句中占位符的具体值,才能执行语句。如下面的程序段,根据ID的取值更新EMPLOYEES表中SALARY字段的取值,将第一个占位符代表的参数设置为10000.00,将第二个占位符代表的参数设置为111,语句执行的结果是EMPLOYEES表中ID为111的记录的SALARY取值为10000.00。PreparedStatement pstmt=con.prepareStatement(UPDATE EMPLOYEES SET SALARY=?WHERE ID=?);pstmt.setBigDecimal(1,10000.00)pstmt.setInt(2,111);pstmt.executeUpdate();类PreparedStatement提供的常用方法如下:public boolean execute()throws SQLException 执行PreparedStatement对象中的任一类型的SQL语句。如果返回true,则调用getResultSet方法取得ResultSet集;如果返回false,则调用getUpdateCount方法获得更新数。public ResultSet executeQuery()throws SQLException 执行SQL查询,并返回查询产生的结果集。public int executeUpdate()throws SQLException 执行对象中的SQL语句。如果是一些更新操作,如插入(INSERT)、修改(UPDATE)和删除(DELETE)等,则返回操作的个数。常用的设置方法为:public void setBigDecimal(int parameterIndex,BigDecimal x)throws SQLException 在第parameterIndex位置设置BigDecimal型x。public void setBoolean(int parameterIndex,boolean x)throws SQLException 在第parameterIndex位置设置布尔型x。public void setByte(int parameterIndex,byte x)throws SQLException在第parameterIndex位置设置字节型x。public void setBytes(int parameterIndex,byte x)throws SQLException在第parameterIndex位置设置字节数组型x。public void setDouble(int parameterIndex,double x)throws SQLException在第parameterIndex位置设置双精度型x。public void setFloat(int parameterIndex,float x)throws SQLException 在第parameterIndex位置设置单精度型x。public void setInt(int parameterIndex,int x)throws SQLException 在第parameterIndex位置设置整型x。public void setLong(int parameterIndex,long x)throws SQLException在第parameterIndex位置设置长整型x。public void setNull(int parameterIndex,int sqlType)throws SQLException 在第parameterIndex位置设置为空x。public void setObject(int parameterIndex,Object x)throws SQLException 在第parameterIndex位置设置对象x。public void setShort(int parameterIndex,short x)throws SQLException 在第parameterIndex位置设置短整型x。void setString(int parameterIndex,String x)throws SQLException 在第parameterIndex位置设置字符串型x。public void setTime(int parameterIndex,Time x)throws SQLException 在第parameterIndex位置设置时间型x。public void setTimestamp(int parameterIndex,Timestamp x)throws SQLException在第parameterIndex位置设置时间戳型x。9.2.6 ResultSet Result对象是指一张数据表,代表数据库结果集,通常是通过执行查询数据库的语句而产生的。ResultSet对象持有一个游标,该游标指向当前数据行。初始化时游标定位到第一行之前。Next方法将游标移动到下一行,当对象行完时,返回错误。通常使用循环来完成每行的遍历。public boolean next()throws SQLException 读行,返回true;行数完,则返回false。例如,下面程序段完成对结果集的操作,对所有记录进行遍历并输出其中的字段CID和CPin的值。while(rs.next()String theInt=rs.getString(CID);String str=rs.getString(CPin);System.out.println(CID:+theInt+CPin:+str);结果集有一些方法用于对返回结果的具体字段进行读取,包括以字段编号为参数和以字段名称为参数的读取,其中以字段编号为参数的读取速度快一些,而以字段名称为参数的读取对用户来说更加方便。所谓字段编号是指当前结果集中的第一个列字段编号为1,然后依次加1对剩余列进行编号;而字段名称是指列标题的名字。Get字段的类型同上述Set字段的类型一致。下面是以字段编号为参数的读取方法:public BigDecimal getBigDecimal(int columnIndex)throws SQLException public boolean getBoolean(int columnIndex)throws SQLException public byte getByte(int columnIndex)throws SQLExceptionpublic byte getBytes(int columnIndex)throws SQLExceptionpublic double getDouble(int columnIndex)throws SQLExceptionpublic float getFloat(int columnIndex)throws SQLException public Int getInt(int columnIndex)throws SQLExceptionpublic Long getLong(int columnIndex)throws SQLExceptionpublic Object getObject(int columnIndex)throws SQLException public short getShort(int columnIndex)throws SQLException public String getString(int columnIndex)throws SQLException public java.sql.Time getTime(int parameterIndex,Time x)throws SQLException public java.sql.TimeStamp getTimestamp(int columnIndex)throws SQLException以字段名称为参数的读取方法如下:public BigDecimal getBigDecimal(String columnName)throws SQLException public boolean getBoolean(String columnName)throws SQLException public byte getByte(String columnName)throws SQLExceptionpublic byte getBytes(String columnName)throws SQLExceptionpublic double getDouble(String columnName)throws SQLExceptionpublic float getFloat(String columnName)throws SQLException public Int getInt(String columnName)throws SQLException public Long getLong(String columnName)throws SQLExceptionpublic Object getObject(String columnName)throws SQLException public short getShort(String columnName)throws SQLException public String getString(String columnName)throws SQLException public java.sql.Time getTime(String columnName)throws SQLException public java.sql.TimeStamp getTimestamp(String columnName)throws SQLException9.3 实 例例 【例9.1】给出一个完整的实例,包括建立所需用户数据库,配置ODBC数据源,编写访问数据库的程序,查看运行结果。其中访问数据库程序输出班级为“025”的记录,并将“025”修改为“计算机”。9.3.1 建立用建立用户数据数据库 建立FoxPro数据库,数据库名为Student.mdb,其中一个表为Xuesheng.dbf,记录如图9.1所示。图9.1 表Xuesheng.dbf中的记录9.3.2 配置配置ODBC数据源数据源 在Windows 2000下配置ODBC数据源,首先找到程序管理工具数据源(ODBC),(在Windows 98下,可在控制面板中找到ODBC),调出“ODBC数据源管理器”,如图9.2所示。图9.2 ODBC数据源管理器点击“添加”按钮,出现“创建新数据源”窗口,如图9.3所示。图9.3 为数据源选择驱动程序 在图9.3中选择“Microsoft Visual FoxPro Driver”选项,然后点击“完成”按钮,进入“ODBC Visual FoxPro Setup”窗口,如图9.4所示。图9.4 完成ODBC数据源的配置 (1)“Data Source Name(数据源名)”:ODBC提供给应用程序的数据库名字。在图9.4中填为STU。(2)“Description(描述)”:用来说明数据库的文字信息,可根据自己的需要填写。在图9.4中填为“用于JAVA程序的数据库测试”。(3)“Path(路径)”是ODBC映射数据库的具体路径,可以直接填写,也可以单击“Browse”(浏览)按钮选择一数据库。这里选择的路径为E:_WorkJavaSTUDENT.DBC。(4)点击“OK(确定)”按钮,可以看见“ODBC数据源管理器”窗口多出一个STU数据源。9.3.3 数据数据库访问的步的步骤编写数据库访问程序的步骤如下:(1)引入java.sql的包。import java.sql.*;(2)声明变量。Statement stmt;PreparedStatement pstmt;ResultSet rs;(3)加载驱动程序。Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);(4)连接数据库。String urlName=jdbc:odbc:STU;Connection con=DriverManager.getConnection(urlName,);(5)执行查询操作。rs=stmt.executeQuery(SELECT 学号,姓名,班级 from Xuesheng WHERE 班级=025);.pstmt=con.prepareStatement(UPDATE Xuesheng SET 班级=?WHERE 班级=?);pstmt.setString(1,计算机);pstmt.setString(2,025);pstmt.executeUpdate();.(6)关闭数据库。con.close();9.3.4 源程序代源程序代码源程序代码如下:/程序文件名UseJDBC.javaimport java.sql.*;public class UseJDBCpublic static void main(String args)tryStatement stmt;PreparedStatement pstmt;ResultSet rs;/加载JDBC-ODBC桥Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);String urlName=jdbc:odbc:STU;/连接STU数据库 Connection con=DriverManager.getConnection(urlName,);/执行sql查询stmt=con.createStatement();rs=stmt.executeQuery(SELECT 学号,姓名,班级 from Xuesheng WHERE 班级=025);System.out.println(显示所有返回结果:);/遍历结果集while(rs.next()/得到记录值,输出 String strNumber=rs.getString(学号);String strName=rs.getString(姓名);String strClass=rs.getString(3);System.out.println(学号:+strNumber+姓名:+strName+班级:+strClass);/更新班级值pstmt=con.prepareStatement(UPDATE Xuesheng SET 班级=?WHERE 班级=?);pstmt.setString(1,计算机);pstmt.setString(2,025);pstmt.executeUpdate();/关闭连接con.close();catch(Exception e)e.printStackTrace();9.3.5 运行运行结果果 在图9.5中,输出“班级”为“025”的记录中的“学号”、“姓名”和“班级”字段。图9.6为执行更新操作后的表记录。与图9.1相比,可以看到程序操作以前为“025”的“班级”的列值已经更新为“计算机”。图9.5 界面输出图9.6 程序访问后的Xuesheng表习 题 1.创建一个新的Access数据库或者其它类型的数据库,为之建立一个如图9.1所示的表stu。对数据库进行ODBC数据源配置,将它的名字配置成STUDENT。2.编写程序,访问习题1配置的STUDENT库中的表stu,输出所有女生的学号、姓名和班级,然后存到文件stu_female中。3.编写程序,访问习题1配置的STUDENT库中的表stu,将学号以“02037”开头的学生的班级更新为“英语班”。4.编写Applet,实现到习题1配置的STUDENT库中的表stu的访问,界面上使用文本区域按行输出所有男生的记录。谢谢大家!
展开阅读全文