E N D
JDBC和数据库 冯天宇
JDBC简介 • JDBC(Java DataBase Connectivity)是Java语言用来连接和操作关系型数据库的应用程序接口(API)。JDBC由一群类(Class)和接口(Interface)所组成,通过调用这些类和接口所提供的方法,我们可以连接不同的数据库,对数据库下达SQL命令并取得行结果。对程序开发人员来说,在Java程序中使用JDBC API来操作数据库最大的好处是只要撰写一次程序,然后搭建不同的JDBC驱动程序,便可以操作不同的数据库,而在JSP程序中使用JDBC的API来连接数据库,更可以让前端使用者无须事先安装任何的程序,只需要通过浏览器便可以存取远程数据库。
JDBC驱动程序的分类 • 目前有四种可供使用的JDBC驱动程序,不同类型的的驱动程序有着不一样的使用方法,所以当我们在连接数据库之前,必须先依照我们的需求选择一个适当的驱动程序,这四种不同类型的驱动程序分别是:
JDBC-ODBC Bridge,桥接器型的驱动程序,这类驱动程序的特色是必须在使用者端的计算机上事先安装好ODBC驱动程序,然后通过JDBC-ODBC的调用方法,进而通过ODBC类存取数据库。 • JDBC-Native API Bridge,也是桥接器型驱动程序之一,如同类型一,这类型的驱动程序也必须先在使用者计算机上安装好特定的驱动程序(类似ODBC),然后通过JDBC-Native API桥接器的转换,把JAVA API调用转换成特定驱动程序的调用方法,进而存取数据库。
JDBC-middleware,这类型的驱动程序最大的好处是省去了在使用者计算机上安装任何驱动程序的麻烦,只需在服务器端安装好middleware,而middleware会负责所有存取数据库时必要的转换。JDBC-middleware,这类型的驱动程序最大的好处是省去了在使用者计算机上安装任何驱动程序的麻烦,只需在服务器端安装好middleware,而middleware会负责所有存取数据库时必要的转换。 • Pure JDBC driver,这类型的驱动程序是最成熟的JDBC驱动程序,不但无需在使用者计算机上安装任何额外的驱动程序,也不需在服务器端安装任何的中介程序(middleware),所有存取数据库的操作,都直接由驱动程序来完成。
一般而言,我们建议您不使用桥接器型的驱动程序,这类型的驱动程序不是用纯JAVA语言所开发,这使得程序的可移植性会变差,而且还需要事先安装其它的特定驱动程序在使用者计算机上,非常的麻烦。反观类型三和类型四的驱动程序,不但使程序的可移植性提高,达到跨平台的目的,还省去在使用者计算机上安装其他驱动程序的麻烦,可谓一举数得。所以当我们在为我们的数据库选择驱动程序时,应尽量以类型三和类型四的JDBC驱动程序为主,而类型一和二则为次要的选择。一般而言,我们建议您不使用桥接器型的驱动程序,这类型的驱动程序不是用纯JAVA语言所开发,这使得程序的可移植性会变差,而且还需要事先安装其它的特定驱动程序在使用者计算机上,非常的麻烦。反观类型三和类型四的驱动程序,不但使程序的可移植性提高,达到跨平台的目的,还省去在使用者计算机上安装其他驱动程序的麻烦,可谓一举数得。所以当我们在为我们的数据库选择驱动程序时,应尽量以类型三和类型四的JDBC驱动程序为主,而类型一和二则为次要的选择。
JDBC常用类与方法 • DriverManager类 这个类负责管理JDBC驱动程序。我们使用JDBC驱动程序之前,我们必须先将驱动程序加载并向DriverManager注册后才可使用,在程序中可以通过Class.forName()这个标准函数来完成。 DriverManager类也提供方法让我们建立与数据库的连接。如下表所示:
JDBC常用类与方法 表 1
下面的范例将示范如何连接数据库 <%@page language= " java " %> <%@page import= " java.sql.* " %> <%@page contentType= " text/html;charset=GB2312" %> <html> <head> <title>新增记录(Record)范例</title> </head> <body bgcolor=“#FFFFFF”> <% String driver="org.postgresql.Driver"; String url= "jdbc:postgresql:test"; String user = "webuser"; String password = "webuser"; Class.forName(driver); Connection con=DriverManager.getConnection(url,user,password); …… con.close(); %> </body> </html>
这个程序示范了如何连接到postgreSQL数据库,先看这一行:这个程序示范了如何连接到postgreSQL数据库,先看这一行: <%page import=“java.sql.*”%> 因为在我们的范例中用到了JDBC提供的类和方法,所以在程序的开头一定要加上这一行,否则将发生编译错误。紧接着下面这一行: <%page content=“text/html;charset=GB2312”%> 只要我们希望在JSP网页中存取数据库中的中文,都必须在程序的开头加上这一行,否则也将造成编译上的错误。
接下来这一行: Class.forName(driver); 便是通过java.lang.Class类提供的标准方法forName()来向DriverManager注册并加载我们想要使用的JDBC驱动程序,在这个范例中,我们使用的是postgreSQL的JDBC驱动程序。 关于Class.forName(driver)方法中driver参数的设定,会因为不同的JDBC驱动程序而有不同的设定,如何正确设定请参照各个驱动程序的说明文件。当我们通过Class.forName()方法正确的注册并加载JDBC驱动程序后,接下来就要建立和数据库的连接。
请看下面这一行: Connection con= DriverManager.getConnection(url,user,password); 我们利用java.sql.DriverManager类提供的getConnection()方法来建立与数据库的连接,其中参数url指定了数据库的位置,user指定连接数据库时的使用者名称,password指定连接数据库时的密码。关于url的指定方法,一般的格式如下: jdbc:<subprotocol>:<subname> 在我们的范例程序中我们指定的url如下: url=“jdbc:postgresql:test”; 其中在<subprotocol>的部分我们指定postgreSQL为我们所要连接的数据库类型,在<subname>的部分我们则指定了所要使用的数据库名称test。让我们再来看一个url的例子: jdbc:odbc:mydata 这个例子显示出我们通过jdbc:odbc bridge连接到mydata数据库。当我们调用DriverManager.getConnection()方法之后,便会得到一个负责和数据库连接的Connection类的对象,至此,我们便已顺利的连接好数据库。
JDBC常用类与方法 • Connection类 Connection类对象负责维护JSP/Java数据库程序和数据库之间的联机。通过Connection类提供的方法,我们可以建立另外三个非常有用的类对象,分别是Statement类、PreparedStatement类和Database Meta Data类,下面我们会分别针对这些类再做详细的说明。
JDBC常用类与方法 • Statement类 通过Statement类所提供的方法,我们可以利用标准的SQL命令,对数据库直接进行新增、删除或修改记录(Record)的操作。见表3。
JDBC常用类与方法 表 3
现在让我们通过范例程序来说明如何使用Statement类所提供的方法操作我们的数据库。下面的范例程序将test数据库内的phonebook数据表内新增一笔记录。现在让我们通过范例程序来说明如何使用Statement类所提供的方法操作我们的数据库。下面的范例程序将test数据库内的phonebook数据表内新增一笔记录。 <%@page language= " java " %> <%@page import= " java.sql.* " %> <%@page contentType= " text/html;charset=GB2312" %> <html> <head> <title>新增记录(Record)范例</title> </head> <body bgcolor=“#FFFFFF”> <% String driver="org.postgresql.Driver"; String url= "jdbc:postgresql:test"; String user = "webuser"; String password = "webuser";
Class.forName(driver); try { Connection con=DriverManager.getConnection(url,user,password); Statement smt=con.createStatement(); smt.executeUpdate(“INSERT into phonebook(name,phone,addr,birth)” +“ values(‘张小强’,‘12345678’,‘西安市南窑头’,” +“TO_DATE(‘1980/02/30’, ‘YYYY/MM/DD’)”); smt.close(); con.close(); } catch(SQLException SE) { SE.printStackTrace(); } %> </body> </html>
当我们得到一个Connection类的对象之后,紧接着便利用Connection类所提供的方法createStatement()建立一个Statement类对象,接着我们来看这一行程序代码:当我们得到一个Connection类的对象之后,紧接着便利用Connection类所提供的方法createStatement()建立一个Statement类对象,接着我们来看这一行程序代码: smt.executeUpdate(“INSERT intophonebook(name,phone,addr,birth)” +“ values(‘张小强’,‘12345678’,‘西安市南窑头’,” +“TO_DATE(‘1980/02/30’, ‘YYYY/MM/DD’)”); 我们将一个标准的SQL命令INSERT语句当成字符串参数传给executeUpdate()方法,紧接着executeUpdate()方法便会通过由Connection类对象所维护的数据库连接,实际将SQL命令传给数据库以进行新增记录的操作。
Note:executeQuery()方法和executeUpdate()方法的使用方式是相当类似的,它们都需要传入一个标准的SQL命令作为参数,主要的差别在于executeQuery()方法是专门处理查询操作的。当我们使用SQL命令SELECT语句对数据库做查询时,就必须用executeQuery()方法,而executeQuery()方法会建立一个RecordSet类的对象保存查询的结果,除了SELECT命令之外的其它SQL命令,如INSERT、DELETE、UPDATE、DROP等操作数据库的语句,我们就可以通过executeUpdate()方法来执行。Note:executeQuery()方法和executeUpdate()方法的使用方式是相当类似的,它们都需要传入一个标准的SQL命令作为参数,主要的差别在于executeQuery()方法是专门处理查询操作的。当我们使用SQL命令SELECT语句对数据库做查询时,就必须用executeQuery()方法,而executeQuery()方法会建立一个RecordSet类的对象保存查询的结果,除了SELECT命令之外的其它SQL命令,如INSERT、DELETE、UPDATE、DROP等操作数据库的语句,我们就可以通过executeUpdate()方法来执行。
JDBC常用类与方法 • PreparedStatement类 PreparedStatement类和Statement类的不同之处在于PreparedStatement类对象会将传入的SQL命令事先编好等待使用,所以当我们有单一的SQL指令被执行多次时,用PreparedStatement类会比用Statement类来得有效率。如表3所示。
在下面这个程序中我们将示范如何使用PreparedStatement类对象来更新数据库中的记录。在下面这个程序中我们将示范如何使用PreparedStatement类对象来更新数据库中的记录。 <%@page language= " java " %> <%@page import= " java.sql.* " %> <%@page contentType= " text/html;charset=GB2312" %> <html> <head> <title>修改记录(Update)范例</title> </head> <body bgcolor=“#FFFFFF”> <% String driver="org.postgresql.Driver"; String url= "jdbc:postgresql:test"; String user = "webuser"; String password = "webuser";
Class.forName(driver); try { Connection con=DriverManager.getConnection(url,user,password); PreparedStatement psmt=con.prepareStatement(“UPDATE phonebook ” +“set phone=?,addr=? ” +“where name=?”); psmt.setString(1,“87654321”); psmt.setString(2,“西安市高新区软件园”); psmt.setString(3,“张小强”); psmt.executeUpdate(); psmt.close(); con.close(); } catch(SQLException SE) { SE.printStackTrace(); } %> </body> </html>
首先,我们使用Connection类提供的preparedStatement()方法来建立PreparedStatement类对象,在这需要注意的是PreparedStatement类的“IN”参数,也就是SQL命令中以“?”代替的部分,“IN”参数的类型必须和数据库表格的字段(Field)类型一致,PreparedStatement类提供一系列的“set类型()”方法让我们可以把java的数据类型转换成适当的字段类型,最后使用executeUpdate()方法把我们的SQL命令传给数据库以完成修改记录的操作。首先,我们使用Connection类提供的preparedStatement()方法来建立PreparedStatement类对象,在这需要注意的是PreparedStatement类的“IN”参数,也就是SQL命令中以“?”代替的部分,“IN”参数的类型必须和数据库表格的字段(Field)类型一致,PreparedStatement类提供一系列的“set类型()”方法让我们可以把java的数据类型转换成适当的字段类型,最后使用executeUpdate()方法把我们的SQL命令传给数据库以完成修改记录的操作。
JDBC常用类与方法 • ResultSet类 当我们使用SELECT命令来对数据库做查询时,数据库会响应我们查询的结果,而ResultSet类对象负责存储我们查询数据库的结果。值得一提的是ResultSet类实际上作了一系列的方法让我们即使不使用标准的SQL命令也能对数据库进行新增、删除和修改记录(Record)的操作。另外,ResultSet类对象也负责维护一个记录指针(Cursor),记录指针指向数据表格(Table)中的某个记录,通过适当的移动记录指针,我们可以随心所欲的存取数据库,进而加强程序的效率。如表4。
下面的程序将示范如何使用ResultSet类 所提供的方法来移动记录指针并且读取记录指针所指向记录的字段(Field)值。 <%@page language= " java " %> <%@page import= " java.sql.* " %> <%@page contentType= " text/html;charset=GB2312" %> <html> <head> <title>记录指针(Cursor)范例</title> </head> <body bgcolor=“#FFFFFF”> <% String driver="org.postgresql.Driver"; String url= "jdbc:postgresql:test"; String user = "webuser"; String password = "webuser";
Class.forName(driver); try { Connection con=DriverManager.getConnection(url,user,password); Statement smt= con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rst=smt.executeQuery(“SELECT * from phonebook”); %> <table width=“50%” border=“2”> <% rst.beforeFirst(); //移动记录指针到第一条记录之前 out.println(“所有记录:”); while(rst.next()) //移动记录指针到下一条记录 { %> <tr> <td><%=rst.getString(1)%></td> <td><%=rst.getString(2)%></td> <td><%=rst.getString(3)%></td> <td><%=rst. getDate(4)%></td> </tr>
<% } %> </table><p> <% rst.first(); //移动记录指针到第一条记录 out.println(“第一条记录:”); %> <table width=“50%” border=“2”> <tr> <td><%=rst.getString(1)%></td> <td><%=rst.getString(2)%></td> <td><%=rst.getString(3)%></td> <td><%=rst.getDate(4)%></td> </tr> </table><p> <% rst.last(); //移动记录指针到最后一条记录 out.println(“最后一条记录:”); %>
<table width=“50%” border=“2”> <tr> <td><%=rst.getString(1)%></td> <td><%=rst.getString(2)%></td> <td><%=rst.getString(3)%></td> <td><%=rst. getDate(4)%></td> </tr> </table><p> <% rst.absolute(3); //移动记录指针到第三条记录 out.println(“第三条记录:”); %> <table width=“50%” border=“2”> <tr> <td><%=rst.getString(1)%></td> <td><%=rst.getString(2)%></td> <td><%=rst.getString(3)%></td> <td><%=rst. getDate(4)%></td> </tr> </table><p>
<% rst.close(); smt.close(); con.close(); } catch(SQLException SE) { SE.printStackTrace(); } %> </body> </html> 我们使用Statement类提供的方法executeQuery()查询数据库并将结果保存在ResultSet类对象中,请看这一行: ResultSet rst=smt.executeQuery(“SELECT * from phonebook”); executeQuery()方法将查询phonebook数据表的结果保存在Result类对象中。我们在程序中使用了几个移动记录指针的方法,分别是beforeFirst()、first()、last()、absolute()和next(),并且使用getstring()方法取得phonebook数据表内记录指针所指向记录的四个字段值。
JDBC常用类与方法 • DatabaseMetaData类 DatabaseMetaData类保存了数据库的所有特性,并且提供许多的方法来取得这些信息,详细的使用方法请参照JDBC说明文件。
JDBC常用类与方法 表 5
JDBC常用类与方法 • ResultSetMetaData类 ResultSetMetaData类对象保存了所有ResultSet类对象中关于字段(Field)的信息,并且也提供了许多方法来取得这些信息。如表6所示。
JDBC常用类与方法 表 6
JDBC连接数据库的模式与步骤 • 加载驱动程序 Class.forName(driver); • 建立连接 Connection con=DriverManager.getConnection(url); • 创建语句对象 Statement stmt=con.createStatement(); • 执行查询语句 ResultSet rs=stmt.executeQuery(sql); • 查询结果处理及关闭结果集对象 rs.close(); • 关闭语句对象 stmt.close(); • 关闭连接 con.close(); driver Connection Statement close ResultSet
本讲结束 谢谢! QQ:3569452