JDBC连接数据库.ppt
第七章 JDBC连接数据库,JDBC工作原理 通过JDBC对数据库执行SQL语句 基于数据源访问数据库 高级开发技巧,本章主要内容,JDBC工作原理 通过JDBC对数据库执行SQL语句 基于数据源访问数据库 高级开发技巧,JDBC(Java DataBase Connectivity,中文意为Java数据库连接)是在Java中用面向对象的方法来连接数据库的技术。JDBC支持基本SQL语句,提供多样化的数据库连接方式,为各种不同的数据库提供统一的操作界面 作为特定厂商数据库访问API的一种高级抽象,它主要包含一些通用的接口类。真正的数据库访问操作实现是由各自数据库厂商提供的。通常把厂商提供的特定于数据库的访问API称为数据库JDBC驱动程序。,JDBC通过提供一个抽象的数据库接口,使得程序开发人员在编程时可以不用绑定在特定数据库厂商的API上,大大增加了应用程序的可移植性。在实际运行过程中程序代码通过JDBC访问数据库时,仍旧需要调用特定于数据库的访问API!,JDBC访问数据库层次结构,目前,比较常见的JDBC驱动程序可分为以下4种类型:(1)JDBC-ODBC桥加ODBC驱动程序:JDBC-ODBC桥产品利用ODBC驱动程序提供JDBC访问。在服务器上必须可以安装ODBC驱动程序。(2)本地API:这种类型的驱动程序把客户机API上的JDBC调用转换为Oracle、Sybase、Informix、DB2或其它DBMS的调用。,(3)JDBC网络纯Java驱动程序:这种驱动程序将JDBC转换为与DBMS无关的网络协议,之后这种协议又被某个服务器转换为一种DBMS协议。这种网络服务器中间件能够将它的纯Java客户机连接到多种不同的数据库上。(4)本地协议纯Java驱动程序:这种类型的驱动程序将JDBC调用直接转换为DBMS所使用的网络协议。这将允许从客户机机器上直接调用DBMS服务器,是Intranet访问的一个很实用的解决方法。第3类和第4类驱动程序将成为JDBC访问数据库的首选方法。第1类和第2类驱动程序在直接的纯Java驱动程序还没有上市前会作为过渡方案来使用。,7.2 创建与数据库连接 从编程角度出发,有两个类负责与数据库建立连接,第一个是DriverManager,它是JDBC API提供的为数不多的实际类之一,DriverManager负责管理已注册驱动程序的集合,实质上就是提取使用驱动程序的细节,这样程序员就不必直接处理它们。第二个类是实际处理的JDBC Driver 类,它是由独立厂商提供的,负责建立数据库连接和处理所有与数据库的通信。,创建数据库连接,分为以下几步:(1)首先注册数据库驱动程序(2)然后根据具体的JDBC URL地址,调用DriverManager对象的getConnection()来获取一个代表数据库连接的java.sql.connection对象。,注册数据库驱动程序:要加载要使用的数据库驱动程序类,该工作由Class类的静态方法forName完成,它加载相应的驱动程序类,并创建该类的一个实例。如要加载JDBC-ODBC桥驱动类采用如下语句:Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);,使用MySQL 的JDBC驱动程序的加载语句如下:Class.forName(org.gjt.mm.mysql.Driver);使用Oracle8i的JDBC驱动程序的语句如下:Class.forName(oracle.jdbc.driver.OracleDriver);使用SQL SERVER的JDBC驱动程序的加载语句如下:Class.forName(com.microsoft.jdbc.sqlserver.SQLServerDriver);,JDBC URL 如果很多不同的驱动程序都可能被实际注册过,DriverManager选择正确驱动程序的方法是:每个JDBC驱动程序使用一个专门的JDBC URL作为自我标志的一种方法,DriverManager通过JDBC URL来选择正确的驱动程序。JDBC URL 的格式如下:jdbc:子协议:数据库定位器。,MySQL数据库:jdbc:mysql:/机器名/数据库名Oracle数据库:jdbc:oracle:thin机器名:端口名:数据库名,根据给定具体的JDBC URL,获取数据库连接的方法是在DriverManager对象上调用getConnection()。这种方法有两种形式:DriverManager.getConnection(url)DriverManager.getConnection(url,user,password)其中第二种方式需要输入用户名和密码信息进行身份认证。,使用SQL SERVER的连接语句如下:String url=jdbc:microsoft:sqlserver:/localhost:1433;DatabaseName=pubs;String user=sa;String password=;Connection conn=DriverManager.getConnection(url,user,password);,Oracle提供了2种JDBC驱动程序:JDBC OCI驱动程序Connection con=DriverManager.getConnection(jdbc:oracle:oci8:db,scott,tiger);JDBC Thin驱动程序Connection con=DriverManager.getConnection(jdbc:oracle:thin:host:1521:db,scott,tiger);,程序71:test.jsp,连接Mysql数据库成功!,数据库连接测试,JDBC工作原理 通过JDBC对数据库执行SQL语句 基于数据源访问数据库 高级开发技巧,创建和执行简单的SQL语句 java.sql.Statement 对象代表一条发送到数据库执行的SQL语句。有三种 Statement 对象:Statement 对象用于执行不带参数的简单 SQL 语句;PreparedStatement 对象用于执行带或不带参数的预编译 SQL 语句;CallableStatement 对象用于执行对数据库存储过程的调用。,Statement 对象将 SQL 语句发送到 DBMS 由Connection对象的createStatement()方法创建Statement对象:Connection con=DriverManager.getConnection(“url”,“帐号”,“密码”)Statement stmt=con.createStatement();,Statement接口提供的执行SQL语句的常用方法:executeQuery():用于产生单个ResultSet的语句。例如SELECT语句。stmt.executeQuery(query);,execute()返回布尔值,用于执行任何 SQL 语句,返回多个结果集、多个更新计数或二者组合的语句。stmt.execute();通常:ResultSet rs stmt.executeQuery(query);,executeUpdate()用来创建和更新表,用于执行INSERT、UPDATE或DELETE语句以及SQL DDL语句,例如CREATE TABLE和DROP TABLE。INSERT、UPDATE或DELETE语句的效果是修改表中零行或多行中的一列或多列,该方法返回一个整数,指示受影响的行数(即更新计数)。对于CREATE TABLE和DROP TABLE等不操作行的数据,方法的返回值总为零。stmt.executeUpdate(query);,ResultSet对象 ResultSet对象是executeQuery()方法的返回值,被称为结果集,它代表符合SQL语句条件的所有行。ResultSet 对象包含 SQL 语句的执行结果。它通过一套get方法提供了对这些行中数据的访问,即使用 getXXX 方法检索数据getInt()用于检索整型值getString()用于检索字符串值,说明:上述get方法很多,究竟用哪一个getXXX()方法,由列的数据类型来决定。同一种类型的getXXX()方法是成对出现的,一个是根据列号得到值,另一个是根据列名得到值。结果集游标即可以从第一行移动到最后一行,也可以从最后一行移动到第一行。在java.sql包中有很多对象都有getWarnings()方法,这里的getWarnings()是与结果集相关的警告,ResultSet中的主要方法:public int getInt(int columnIndex)throws SQLExceptionpublic int getInt(String columnName)throws SQLExceptionpublic String getString(int columnIndex)throws SQLExceptionpublic String getString(String columnName)throws SQLExceptionboolean next()/将游标移动到结果集的下一行boolean previous()/将游标移动到结果集的上一行 void close()/关闭结果集boolean wasNull()/检测结果集是否为空boolean first()/移动游标到ResultSet结果集的第一行boolean last()等等,行和游标ResultSet对象自动维护指向其当前数据行的游标。每调用一次next()方法,游标向下移动一行。最初它位于第一行之前,因此第一次调用next(),将把游标置于第一行上,使它成为当前行。随着每次调用next(),导致游标向下移动一行,按照从上至下的次序获取ResultSet 行。在ResultSet对象或其对应的Statement对象关闭之前,游标一直保持有效。,结果集的游标是有名字的。如果数据库允许定位更新或定位删除,则需要将光标的名字作为参数提供给更新或删除命令。可通过调用方法getCursorName()获得游标名。不是所有的DBMS都支持定位更新和删除。可使用 DatabaseMetaData的supportsPositionedDelete()和supportsPositionedUpdate()方法来检查特定连接是否支持这些操作。,有时候需要结果集的游标前后移动,这时可使用滚动结果集。为了获得滚动结果集,必须先用下面方法得到一个Statement对象:Statement st=con.createStatement(int type,int concurrency);根据type和concurrency的取值,当执行ResultSet r=st.executeQuery()时,会返回不同类型的结果集。,type的取值决定滚动方式,它可以取:ResultSet.TYPE_FORWORD_ONLY:表示结果集只能向下滚动ResultSet.TYPE_SCROLL_INSENSITIVE:表示结果集可以上下滚动,当数据库变化时,结果集不变ResultSet.TYPE_SCROLL_SENSITIVE:表示结果集可以上下滚动,当数据库变化时,结果集同步改变。,concurrency取值表示是否可以用结果集更新数据库,它的取值是:ResultSet.CONCUR_READ_ONLY:表示不能用结果集更新数据库的表ResultSet.CONCUR_UPDATETABLE:表示能用结果集更新数据库的表,列方法getXXX()提供了获取当前行中某列值的途径,可按任何次序获取列值,但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。可用列名或列号标识要从中获取数据的列,假设ResultSet对象rs的第二列名为title,并将值存储为字符串,代码:String s=rs.getString(“title”);String s=rs.getString(2);,列是从左至右编号的,并且从列1开始getXXX()方法的输入的列名不区分大小写提供使用列名这个选项是为了让在查询中指定列名的用户可使用相同的名字作为getXXX()方法的参数。如果select语句未指定列名(例如在“select*from table1”中或列是导出的时),则应该使用列号,有些情况下,SQL查询返回的结果集中可能有多个列具有相同的名字。如果列名用作getXXX()方法的参数,则getXXX()将返回第一个匹配列名的值。因而,如果多个列具有相同的名字,则需要使用列索引来确保检索了正确的列值。这时应使用列号。如果列名已知,但不知其索引,则可用方法findColumn()得到其列号,关于ResultSet中列的信息,可通过调用ResultSet的方法getMetaData()得到。返回的ResultSetMetaData对象将给出其ResultSet对象各列的编号、类型和属性。作为一种好的编程风格,应在不需要Statement对象和Connection对象时显式地关闭它们。,程序example1代码描述:import.URL;import java.sql.*;import oracle.jdbc.driver.*;Class.forName(oracle.jdbc.driver.OracleDriver);Connection con=DriverManager.getConnection(jdbc:oracle:oci8:oradb,scott,tiger);,Statement stmt=conn.createStatement();ResultSet r=stmt.executeQuery(SELECT a,b,c FROM Table1);While(r.next()int i=r.getInt(a);String s=r.getString(b);float f=r.getFloat(c);System.out.println(ROW=+i+s+f);stmt.close();con.close();,customer.jsp:%java.sql.Connection conn;java.lang.String strConn;java.sql.Statement sqlStmt;/语句对象 java.sql.ResultSet sqlRst;/结果集对象 tryClass.forName(org.gjt.mm.mysql.Driver).newInstance();conn=java.sql.DriverManager.getConnection(jdbc:mysql:/localhost:3306/sample,root,);,sqlStmt=conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY);/执行Sql语句 String sqlQuery=select customerid,address,phone from customer;sqlRst=sqlStmt.executeQuery(sqlQuery);%,顾客信息表 ID 地址 电话,通过JDBC-ODBC桥使用数据库 无论访问什么数据库,使用JDBC-ODBC桥的方法完全一样,即先注册32位数据源,再按照步骤(注册和加载驱动器、与数据库建立连接、发送SQL语句和处理结果)使用数据库.,设置一个数据源。在控制面板上选择管理工具,然后ODBC数据源,双击ODBC数据源图标,出现如图所示界面.,顺序查询在example2.jsp中,查询student表中的全部记录,运行结果如图所示。,example2.jsp:%Connection con;Statement sql;ResultSet rs;tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e),try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement();rs=sql.executeQuery(SELECT*FROM student);out.print();out.print();out.print(+学号);out.print(+姓名);out.print(+操作系统);out.print(+微机原理);out.print(+数据结构);out.print();,while(rs.next()out.print();out.print(+rs.getString(1)+);out.print(+rs.getString(2)+);out.print(+rs.getInt(czxt)+);out.print(+rs.getInt(wjyl)+);out.print(+rs.getInt(sjjg)+);out.print();out.print();con.close();catch(SQLException e1)%,在example3.jsp中,查询student表中“微机原理成绩大于90”的记录,运行结果如图所示。,=90);,out.print();out.print();out.print(+姓名);out.print(+微机原理);out.print();while(rs.next()out.print();out.print(+rs.getString(2)+);out.print(+rs.getInt(wjyl)+);out.print();out.print();con.close();catch(SQLException e1)%,随机查询example4.jsp查询student表中的全部记录,并将结果逆序输出,最后单独输出第5条记录。运行结果如图所示,%String name,number;int czxt,wjyl,sjjg;Connection con;Statement sql;ResultSet rs;,tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e)try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);/返回可滚动的结果集:rs=sql.executeQuery(SELECT*FROM student);/将游标移动到最后一行:rs.last();/获取最后一行的行号:int lownumber=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+);czxt=rs.getInt(czxt);out.print(+czxt+);wjyl=rs.getInt(wjyl);out.print(+wjyl+);,sjjg=rs.getInt(sjjg);out.print(+sjjg+);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(czxt);out.print(czxt+,);,wjyl=rs.getInt(wjyl);out.print(wjyl+,);physics=rs.getInt(sjjg);out.print(sjjg+。);con.close();catch(SQLException e1)%,example5.jsp将结果放到滚动结果集中。用随机数发生器随机选取结果集中的4条记录,显示它们并计算它们的操作系统平均值。运行结果如图所示。,%String xuehao,name;int math;Connection con;Statement sql;ResultSet rs;tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e),try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);/返回可滚动的结果集:rs=sql.executeQuery(SELECT*FROM student);out.print();out.print();out.print(+学号);out.print(+姓名);out.print(+操作系统);,out.print();/将游标移动到最后一行:rs.last();/获取最后一行的行号:int lownumber=rs.getRow();/获取记录数:int number=lownumber;double sum=0;int 抽取数目=4;int old_i=0,0,0,0;int k=抽取数目;int j=0;,while(抽取数目0)int i=(int)(Math.random()*number+1);/随机获取一个1到number之间的数。boolean boo=false;for(int m=0;m);,xuehao=rs.getString(1);/获取该行学号字段的值。out.print(+xuehao+);name=rs.getString(2);/获取该行姓名字段的值。out.print(+name+);czxt=rs.getInt(czxt);/获取改行数学成绩字段的值。out.print(+math+);out.print();sum=sum+math;抽取数目-;old_ij=i;/记录已取出的行号。j+;,out.print();out.print(平均成绩是:+sum/k);con.close();catch(SQLException e1)%,参数查询 example6.jsp输入查询条件,可以按姓名查询成绩,也可以按分数段查询成绩。运行结果如图所示.若按照姓名查询,请求提交byname.jsp,若按照分数段查询,请求提交给byscore.jsp,example6.jsp:成绩查询 输入姓名:,根据分数查询名单:微机原理分数在 和 之间 操作系统分数在 和 之间,byname.jsp:%/获取提交的姓名: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;tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e)try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement();String condition=SELECT*FROM student WHERE xingming=+name+;,rs=sql.executeQuery(condition);out.print();out.print();out.print(+学号);out.print(+姓名);out.print(+操作系统);out.print(+微机原理);out.print(+数据结构);out.print();while(rs.next()out.print();out.print(+rs.getString(1)+);out.print(+rs.getString(2)+);,out.print(+rs.getInt(3)+);out.print(+rs.getInt(4)+);out.print(+rs.getInt(5)+);out.print();out.print();con.close(),byscore.jsp:%/获取提交的分数的最大值和最小值:String wjylmax=request.getParameter(wjylmax);if(wjylmax=null)wjylmax=100;String wjylmin=request.getParameter(wjylmin);if(wjylmin=null)wjylmin=0;,String czxtmax=request.getParameter(czxtmax);if(czxtmax=null)czxtmax=100;String mathmin=request.getParameter(czxtmin);if(czxtmin=null)czxtmin=0;Connection con=null;Statement sql=null;ResultSet rs=null;,tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e)try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement();String eCondition=wjyl=+wjylmin;String mCondition=czxt=+czxtmin;String condition=SELECT*FROM student WHERE+mCondition+and+eCondition;rs=sql.executeQuery(condition);,out.print();out.print();out.print(+学号);out.print(+姓名);out.print(+操作系统);out.print(+微机原理);out.print(+数据结构);out.print();while(rs.next()out.print();out.print(+rs.getString(1)+);out.print(+rs.getString(2)+);,out.print(+rs.getInt(3)+);out.print(+rs.getInt(4)+);out.print(+rs.getInt(5)+);out.print();out.print();con.close();catch(SQLException e)%,排序查询在SQL语句中使用ORDER BY子句对记录进行排序。example7.jsp查询所有学生成绩,并可选择按照3种方式排列记录:按3科总分从高到低排列记录;按姓氏拼音序排列记录;按微机原理成绩排列记录。运行结果如图所示,example7.jsp:查询成绩:按姓氏排序 按总分排序 按微机原理排序,byname1%/获取提交的排序方式:String name=request.getParameter(R);if(name=null)name=;byte b=name.getBytes(ISO-8859-1);name=new String(b);,String number,xingming;Connection con=null;Statement sql=null;ResultSet rs=null;int math,english,physics;tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e)try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement();String condition=SELECT*FROM student ORDER BY xingming;rs=sql.executeQuery(condition);,out.print();out.print();out.print(+学号);out.print(+姓名);out.print(+操作系统);out.print(+微机原理);out.print(+数据结构);out.print(+总成绩);out.print();while(rs.next()out.print();number=rs.getString(1);out.print(+number+);,xingming=rs.getString(2);out.print(+xingming+);math=rs.getInt(3);out.print(+czxt+);english=rs.getInt(4);out.print(+wjyl+);physics=rs.getInt(5);out.print(+sjjg+);int total=czxt+wjyl+sjjg;out.print(+total+);out.print();out.print();con.close();catch(SQLException e)%,更新记录example8.jsp输入学生姓名和成绩,实现更新记录。运行结果如图所示。,example8.jsp输入要修改成绩的同学的姓名:输入新的操作系统成绩:输入新的微机原理成绩:,输入新的数据结构成绩:数据库更新前的数据记录是:%String name,number;int czxt,wjyl,sjjg;Connection con;Statement sql;ResultSet rs;tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e),try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement();rs=sql.executeQuery(SELECT*FROM student);out.print();out.print();out.print(+学号);out.print(+姓名);out.print(+操作系统);out.print(+微机原理);out.print(+数据结构);out.print();,while(rs.next()out.print();number=rs.getString(1);out.print(+number+);name=rs.getString(2);out.print(+name+);math=rs.getInt(3);out.print(+czxt+);english=rs.getInt(4);out.print(+wjyl+);physics=rs.getInt(5);out.print(+sjjg+);out.print();out.print();con.close();catch(SQLException e1),newResult.jsp:%/获取提交的姓名:String name=request.getParameter(name);if(name=null)name=;byte b=name.getBytes(ISO-8859-1);name=new String(b);,String newczxt=request.getParameter(czxt);if(newczxt=null)newczxt=-100;String newwjyl=request.getParameter(wjyl);if(newwjyl=null)newwjyl=-100;String newsjjg=request.getParameter(sjjg);if(newsjjg=null)newsjjg=-100;,Connection con=null;Statement sql=null;ResultSet rs=null;String number,xingming;int czxt,wjyl,sjjg;tryClass.forName(sun.jdbc.odbc.JdbcOdbcDriver);catch(ClassNotFoundException e)try con=DriverManager.getConnection(jdbc:odbc:aaa,);sql=con.createStatement();,String condition1=UPDATE student SET czxt=+newczxt+WHERE xingming=+name+,condition2=UPDATE student SET wjyl=+newwjyl+WHERE xingming=+name+,condition3=UPDATE student SET sjjg=+newsjjg+WHERE xingming=+name+;/执行更新操作:sql.executeUpdate(condition1);sql.executeUpdate(condition2);sql.executeUpdate(condition3);,/显示更新后的表中的记录:%更新后的表的记录:);out.print();out.print(+学号);out.print(+姓名);out.print(+操作系统);out.print(+微机原理);out.print(+数据结构);out.print();,while(rs.next()out.print();number=rs.getString(1);out.print(+number+);xingming=rs.getString(2);out.print(+xingming+);czxt=rs.getInt(3);out.print(+czxt+);wjyl=rs.getInt(4);out.print(+wjyl+);sjjg=rs.getInt(5);out.print(+sjjg+);out.print();,out.print();con.close();catch(SQLException e)%,添加记录example9.jsp输入一个学生的全部信息,实现添加记录。,example9.jsp:添加新的记录到数据库:同学学号:同学