900 likes | 1.04k Views
模块六 数据库连接技术 JDBC. 目标 本模块主要介绍 Java 应用程序如何利用 JDBC 与数据库连接,实现对数据库的访问,以及 JDBC 的主要类在 Java 程序建立与数据库的连接、 SQL 语句操作、处理数据库操作结果中的作用。. 学习本模块涉及哪些重要内容?. 本模块导读
E N D
模块六 数据库连接技术JDBC • 目标 • 本模块主要介绍Java应用程序如何利用JDBC与数据库连接,实现对数据库的访问,以及JDBC的主要类在Java程序建立与数据库的连接、SQL语句操作、处理数据库操作结果中的作用。
学习本模块涉及哪些重要内容? • 本模块导读 • JDBC,即Java 数据库连接的简称(Java Database Connectivity)。众所周知,Microsoft的ODBC(Open Database Connectivity)已成为当今关系数据库访问的标准,为了给Java提供一个与平台无关的数据库标准,使其应用更加广泛,Sun公司将JDBC构架于ODBC之上,换句话说,Java应用程序通过JDBC访问ODBC,再通过ODBC达到访问数据库的目标。 • JDBC由一组用Java语言编写的类组成,它已成为一种供数据库开发者使用的标准API,用户可以用纯Java API来编写数据库应用。利用JDBC API用户可以开发Java程序,将SQL(Structural Query Language)语句发送到相应的任何一种关系数据库。 • 由于Java语言具有健壮性、安全、易使用、易理解和自动下载到网络等优点,因此,它是数据库应用的一个极好的基础语言。
学习本模块涉及哪些重要内容? • 本模块主要介绍Java应用程序如何利用JDBC与数据库连接,实现对数据库的访问,以及JDBC的主要类在Java程序建立与数据库的连接、SQL语句操作、处理数据库操作结果中的作用。 • 本模块要点 • 掌握JDBC工作原理 • 掌握JDBC访问技术 • 掌握JDBC综合应用
任务一 JDBC概述 子任务1 JDBC简介 知识导读 • JDBC基本功能 • 众所周知,Microsoft的ODBC(Open Database Connectivity)已成为当今关系数据库访问的标准,为了给Java提供一个与平台无关的数据库标准,使其应用更加广泛,Sun公司将JDBC构架于ODBC之上,换句话说,Java应用程序通过JDBC访问ODBC,再通过ODBC达到访问数据库的目标。 • 简单地说,JDBC的基本功能就是管理存放在数据库中的数据。具体又可分为:建立与数据库的连接、发送SQL语句、处理数据库操作结果。
任务一 JDBC概述 子任务1 JDBC简介 知识导读 • JDBC接口概况 • JDBC接口分为两个层次,一个是面向程序开发人员的JDBC API,另外一个是底层的JDBC Driver API,在这里主要介绍的是JDBC API,如图8-1所示。 • API在java.sql包中定义,其中包括JDBC API用到的所有类、接口和方法,主要的类有: • DriverManager 驱动程序管理类,它实现驱动程序的装载,为新的数据库连接提供支持,驱动程序要向该类注册后才能被使用。当进行连接时该类根据JDBC连接数据源 URL地址选择匹配的驱动程序。
任务一 JDBC概述 子任务1 JDBC简介 知识导读 • java.sql.Connection 数据库的连接类,其中的方法需要有相应的驱动程序实现。 • java.sql.Statement SQL语句类,它提供执行SQL语句、取得查询结果等方法;该类又有两个子类: • java.sql.PreparedStatement 用于执行预编译的SQL语句。 • java.sql.CallableStatement 存储过程类,用于执行对一个数据库内嵌过程的调用。 • java.sql.ResultSet 结果集类,提供对结果集进行处理的方法。
任务一 JDBC概述 子任务1 JDBC简介
任务一 JDBC概述 子任务2 JDBC简单应用 知识导读 • Java程序利用JDBC来实现对数据库的访问的具体步骤如下: • 通过ODBC建立访问的数据源,其URL地址为url。 • 创建驱动程序管理类的对象。常用的方法如下: Class.forName (数据库驱动程序类) • 建立与数据源的连接。方法如下: Connection con = DriverManager.getConnection (url); • 利用Statement或它的子类对象,实现把SQL语句发送到DBMS。以查询数据库表为例。步骤如下: Statement stmt = con.createStatement(); //建立Statement对象 String query = "SELECT * FROM LoginRecord"; //SQL语句 ResultSet rs = stmt.executeQuery (query); //执行SQL语句,获得结果
任务一 JDBC概述 子任务2 JDBC简单应用 知识导读 • 对返回的记录集rs处理。 • 【案例】为建立一个用户验证系统,设计一个有关用户ID和密码PWD的表LoginRecord • 设计要求如下:如图8-2所示,数据库名为LoginRecord.mdb,编写用户验证程序,输入用户名“abc”和密码“111”,显示“密码正确,欢迎登录”提示;当用户名或密码错误时,显示“用户名或密码错误,请重新登录”提示。
任务一 JDBC概述 子任务2 JDBC简单应用 知识导读 图8-2 “创建新数据源”类型对话框 • 设置ODBC数据源 • 步骤1 选择“开始”“设置”“控制面板”“管理工具”“ODBC数据源”,进入如图8-3所示的“ODBC数据源管理器”,选择“系统DSN”页,单击“添加…”按钮进入如图8-4所示,建立新数据源类型对话框。
任务一 JDBC概述 子任务2 JDBC简单应用 知识导读 • 步骤1 选择“开始”“设置”“控制面板”“管理工具”“ODBC数据源”,进入如图8-3所示的“ODBC数据源管理器”,选择“系统DSN”页,单击“添加…”按钮进入如图8-4所示,建立新数据源类型对话框。 • 步骤2 选择“Microsoft Access Driver”, 按“完成”按钮进入图8-5建立选择新数据源对话框。 • 步骤3 点击“选择”按钮,进入图8-6所示“选择数据库”对话框。 • 步骤4 选择数据库所在位置的路径后,一步一步退出即可。
任务一 JDBC概述 子任务2 JDBC简单应用 图8-3 “ODBC数据源管理器”对话框
任务一 JDBC概述 子任务2 JDBC简单应用 图8-4 “创建新数据源”类型对话框
任务一 JDBC概述 子任务2 JDBC简单应用 图8-5 “创建新数据源”类型对话框
任务一 JDBC概述 子任务2 JDBC简单应用 图8-6 “选择数据库”对话框
任务一 JDBC概述 子任务2 JDBC简单应用 • 与数据库建立连接 • 步骤1 创建驱动程序类的对象。 • 要与数据库建立连接,JDBC必须创建驱动程序类的对象。在本例中使用的是JDBC-ODBC桥驱动程序,这不是加载驱动程序的唯一方法,但却是最常用的方法,使用Class.forName方法显式建立给定驱动程序类名的对象: • Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver"); • 类Class的成员方法forName (string className)达到加载、初始化“sun.jdbc.odbc.JdbcOdbcDriver”这个类对象的作用。该程序段也可以写成: • Class t= Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver");
任务一 JDBC概述 子任务2 JDBC简单应用 • 步骤2 建立与数据源的连接。 • DriverManager类的getConnection方法用于建立与某个数据源的连接。若与由URL指定的数据源建立连接成功,则返回一个Connection类的对象。以后对于这个数据源的操作都将基于这个对象。getConnection方法是DriverManager类中的静态方法。所以使用时不需构造DriverManager类的对象,直接使用类名DriverManager调用就可以了: • Connection con = DriverManager.getConnection (url); • 其中con是由DriverManager.getConnection方法获得的Connection类的对象。在本例中,url即为jdbc:odbc:login。 • 步骤3 检查警告信息。 • 若连接失败,则产生SQLException异常。成功时也可能产生一些警告信息,因此在使用数据库连接前最好先检查这些警告信息。
任务一 JDBC概述 子任务2 JDBC简单应用 • 步骤4 访问数据库。 • 建立数据库连接之后,就可以对数据库进行各种操作了。这种操作最常见的是数据库查询和更新,也可以获得关于数据库表结构的信息。 • 步骤5 关闭连接。 • 当任何一个连接不对数据库操作时,应调用close()方法将其关闭。 • 步骤6 捕获异常。 • 在建立连接和对数据库进行操作过程中,都可能产生异常。在JDBC中经常遇到的异常是SQLException。 • 执行查询语句 • Statement类
任务一 JDBC概述 子任务2 JDBC简单应用 • 执行查询语句 • Statement类 Statement类主要用于一般SQL查询语句。编程步骤如下: • 步骤1 创建Statement对象。 • Connection类的createStatement方法用于建立一个Statement对象。 • Statement stmt = con.createStatement(); • 步骤2 执行查询语句。 • Statement类使用executeQuery方法来执行一查询语句。executeQuery的参数是用字符串类型表达的SELECT语句。它的返回值是一个ResultSet类的对象。例如: • String query = "SELECT * FROM LoginRecord"; • ResultSet r = stmt.executeQuery (query);
任务一 JDBC概述 子任务2 JDBC简单应用 • 该语句将返回表LoginRecord中的所有记录。 • 步骤3 获取和设置选项。 • 对于Statement对象也可以设置许多选项,SetMaxRows设置容纳的最多记录数的选项;getMaxRows方法返回目前结果集能容纳的最多记录数;GetQueryTimeOut设置一个语句的执行等待时间;getQueryTimeOut设置一个语句的执行等待时间,它的参数是以秒为单位的整型值。若驱动程序等待一个语句执行的时间超过了此值,则产生一个SQLExeption。 • 步骤4 关闭Statement。 • 一个无用的Statement对象在垃圾回收时将会被自动关闭,但最好在使用完Statement对象后立即关闭。在关闭Statement对象时,如果其上还有结果集,该结果集也将被关闭。
任务一 JDBC概述 子任务2 JDBC简单应用 • PreparedStatement类 • Statement对象在每次执行SQL语句时,都要将该语句转给数据库,在多次执行同一语句时,这样做的效率较低。使用PreparedStatement类可以提高效率。 • 如果数据库支持预编译,它可以将SQL语句传给数据库做预编译,以后每次执行这个SQL语句时,速度就可以提高很多;如果数据库不支持预编译,则在语句执行时,才将其传给数据库。不过,数据库支不支持预编译对用户来说是透明的。Statement类主要用于一般SQL查询语句。 • PreparedStatement对象的SQL语句还可以接受参数。在语句中指出需要接受哪些参数,然后进行预编译。在每一次执行时,可以给SQL语句传输不同的参数,这样就大大提高了程序的灵活性。 • PreparedStatement类是Statement类派生出来的子类,因此,Statement类中的方法,它都可以使用。其编程步骤如下:
任务一 JDBC概述 子任务2 JDBC简单应用 • 步骤1 创建PreparedStatement对象。 • 从一个Connection对象可以创建一个PreparedStatement对象。在创建时,应该给出要预编译的SQL语句。例如: • PreparedStatement stmt=con. prepareStatement("SELECT * FROM LoginRecord"); • 步骤2 执行查询语句。 • PreparedStatement对象也使用executeQuery方法来执行语句。需要注意,与Statement类不同的是该方法没有参数。这是由于创建PreparedStatement对象时,已经给出了要执行的SQL语句,并进行了预编译。执行时,只需要执行已编译好的语句就可以了。 • ResultSet rs=pstmt.executeQuery(); • 上述语句可以被执行多次,无须重新给出SQL语句。PreparedStatement类也有一个不带参数的execute方法,用于可能返回多个ResultSet语句的执行。
任务一 JDBC概述 子任务2 JDBC简单应用 • 步骤 3 获取和设置选项。 • PreparedStatement类是使用它的父类Statement类的相应方法来获取和设置选项的。 • 步骤 4 关闭对象。 • PreparedStatement对象也使用close()方法来关闭,实际上,它使用父类Statement的close()方法。 • 处理结果集 • 上面介绍了如何执行SQL查询语句,这些语句执行的结果是一个ResultSet类的对象,要想把查询结果返回给用户,必须对对象进行操作。 • ResultSet对象包括一个由查询语句返回的一个表,这个表中包含所有的查询结果。对ResultSet对象的处理必须逐行进行,而对每一行中的各个列(数据项),可以按任何顺序操作。
任务一 JDBC概述 子任务2 JDBC简单应用 • ResultSet对象维持一个指向当前记录的指针。第一次使用next方法时,指针指向结果集的第一个记录,这时可以对第一个记录数据项进行处理。处理完毕后,使用next方法,这个指针将指向下一记录,继续处理该记录的数据。next方法返回的是一个boolean值,若为true,则说明指针成功地移向下一记录,可以对该记录的数据进行处理,相反若为false,则说明没有下一记录,即结果集处理完毕。 • 在对每一记录进行处理时,可以对各个数据项按任意顺序进行处理,不过,按从左至右的顺序可以获得较高的执行效率。ResultSet类的getXXX方法可以从某一数据项中获得结果。其中XXX是JDBC中的Java数据类型,如getInt、getString、getDate等。getXXX方法需要指定要检索的数据项。有两种指定数据项的方法:一种是以一个int值作为数据项的序号,另一种是以String类型的数据项名来访问数据项的值,这里使用的是后一种方法。
任务一 JDBC概述 子任务2 JDBC简单应用 • 以下是使用的查询结果的程序: String query = "SELECT * FROM LoginRecord "; ResultSet r = stmt.executeQuery (query); while(r.next()){ String r1=r.getString("ID"); String r2=r.getString("PWD"); } • 通常情况下,使用executeQuery或executeUpdate来执行SQL语句。executeQuery用来执行查询语句,它返回一个ResultSet对象。executeUpdate用来执行更新语句,它返回更新的记录数。
任务一 JDBC概述 子任务2 JDBC简单应用 • 然而,在某些情况下,在语句执行前,并不知道是否返回一个结果集。另外某些存储过程可能返回多个结果集和更新记录数。这就需要有一种机制来处理多个结果集和更新记录数。这时可使用execute方法,并使用getResultSet、getUpdateCount和getMoreResults方法来处理返回结果集和更新记录数。 • 对于Statement对象,可以使用execute(String sql)方法,而对于PreparedStatement对象和CallableStatement对象, 可以使用execute()方法,它们都返回一个boolean值指示第一个结果的类型。如果第一个结果是ResultSet类型,则返回true,否则返回false。 • 如果当前结果是ResultSet类型,要使用getResultSet方法获取当前结果集。然后如前所述,对结果集进行操作。
任务一 JDBC概述 子任务2 JDBC简单应用 • 如果当前结果是一个更新记录数,可以使用getUpdateCount()方法来获取其值。如果当前结果是一个ResultSet对象或不再有结果,getUpdateCount()方法返回-1。应该首先检验一个结果是否为ResultSet类型,若不是,则可能是更新记录数,或不再有结果。 • getMoreResults返回一个boolean值,如果下一个结果是ResultSet类型,则返回true,否则返回false。判断不再有结果的条件是(!getMoreResults()&&(getUpdateCount=-1))。 • 通过上述三种方法交替使用,就可以依次处理各个结果集和更新计数。
任务一 JDBC概述 子任务2 JDBC简单应用 • 完整的程序代码如下: import java.awt.*; import java.sql.*; import javax.swing.*; public class JD1 extends JFrame{ private JTextField IDField = new JTextField(10); private JPasswordField PWDField = new JPasswordField(10); String ID; String PWD; public static void main(String[] args){ new JD1();
任务一 JDBC概述 子任务2 JDBC简单应用 } public JD1(){ JPanel panel1 = new JPanel(new BorderLayout()); JPanel panel2 = new JPanel(new GridLayout(2,1)); JPanel panel3 = new JPanel(new GridLayout(2,1)); JLabel label2 = new JLabel("用户名:"); JLabel label3 = new JLabel("密码:"); panel2.add(label2); panel3.add(IDField); panel2.add(label3); panel3.add(PWDField); panel1.add(panel2, BorderLayout.WEST);
任务一 JDBC概述 子任务2 JDBC简单应用 panel1.add(panel3, BorderLayout.CENTER); int Choose = JOptionPane.showConfirmDialog(this, panel1, "登录服务器", JOptionPane.OK_CANCEL_OPTION); if(Choose == JOptionPane.OK_OPTION){ ID = IDField.getText(); PWD = String.valueOf(PWDField.getPassword()); JudgeLogin(); } else if(Choose == JOptionPane.CANCEL_OPTION){ System.exit(0); } }
任务一 JDBC概述 子任务2 JDBC简单应用 private static final String DBDRIVER = "sun.jdbc.odbc.JdbcOdbcDriver"; private static final String DBURL ="jdbc:odbc:login"; private void JudgeLogin(){ Connection con = null; 【1】 PreparedStatement ps = null; 【2】 Statement stmt = null; 【3】 ResultSet rs = null; 【4】 try{ Class.forName(DBDRIVER); con = DriverManager.getConnection(DBURL); 【5】 System.out.println("与数据库建立连接成功!"); }catch (final ClassNotFoundException e){
任务一 JDBC概述 子任务2 JDBC简单应用 System.err.println("ClassNotFoundException:" + e.getMessage()); System.exit(1); }catch (final SQLException e){ System.err.println("SQLException:" + e.getMessage()); System.exit(1); } try{ stmt = con.createStatement();【6】 ps = con.prepareStatement("select PWD from LoginRecord where ID=?");【7】
任务一 JDBC概述 子任务2 JDBC简单应用 ps.setString(1, ID); rs = ps.executeQuery();【8】 if(rs.next()){ if(rs.getString("PWD").equals(PWD)){ JOptionPane.showMessageDialog( null , "账号正确,欢迎登录!", "登录成功",JOptionPane.PLAIN_MESSAGE) ; }else { JOptionPane.showMessageDialog( null , "密码错误,请重新登录", "登录失败" , JOptionPane.ERROR_MESSAGE) ; } }else{
任务一 JDBC概述 子任务2 JDBC简单应用 JOptionPane.showMessageDialog( null , "用户名错误,请重新登录!", "登录失败" , JOptionPane.ERROR_MESSAGE) ; } }catch(final SQLException e){ System.err.println("SQLException:" + e.getMessage()); }finally{ if(stmt != null){ try{ stmt.close(); }catch(final SQLException e){ } }
任务一 JDBC概述 子任务2 JDBC简单应用 if(con != null){ try{ con.close(); }catch(final SQLException e){ } } } } } • 代码详解 • 建立Connection类的对象,并在【5】处将其实例化,建立数据库的连接对象con。
任务一 JDBC概述 子任务2 JDBC简单应用 • 建立PreparedStatement类的对象,并在【7】处将其实例化,建立预编译SQL语句对象ps。 • 建立Statement类的对象stmt,并在【6】处将其实例化,用于把SQL语句发送到DBMS。 • 建立ResultSet rs类的对象rs,并在【8】处将其实例化,建立查询结果集。 • 实现结果 • run: 程序启动界面,如图8-7如示。 • 用户名或密码错误,显示图8-8界面。 • 用户名和密码匹配正确,显示图8-9界面:
任务一 JDBC概述 子任务2 JDBC简单应用 图8-7 登录界面
任务一 JDBC概述 子任务2 JDBC简单应用 图8-8 登录失败界面
任务一 JDBC概述 子任务2 JDBC简单应用 图8-9 登录成功界面
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 • 【案例】编写应用程序,更新数据源“login”的数据库“LoginRecord.mdb”中LoginRecord表记录,然后显示添加记录后的LoginRecord表的所有记录。 • 设计要求如下:设置数据源步骤如上图8-3、8-4、8-5、8-6所示。 • 完整的程序代码如下: import java.sql.*; class JD2{ public static void main (String args[]){
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 String name=null; String password=null; try{ byte by[]=new byte[48]; System.out.println("请输入用户名:"); int i=System.in.read(by); name=new String(by,0,i-1).trim(); System.out.println("请输入密码:"); i=System.in.read(by); password=new String(by,0,i-1).trim(); }catch(Exception e){
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 e.printStackTrace(); } String url="jdbc:odbc:login"; String query="SELECT * FROM LoginRecord"; try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); }catch(java.lang.ClassNotFoundException e){ System.err.print("ClassNotFoundException: "); System.err.println(e.getMessage());
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 } try{ Connection con = DriverManager.getConnection(url); 【1】 Statement stmt = con.createStatement();【2】 PreparedStatement pstmt=con.prepareStatement("INSERT INTO LoginRecord(ID,PWD) VALUES(?,?)");【3】 pstmt.setString(1,name); pstmt.setString(2,password); pstmt.executeUpdate(); pstmt.close();
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 ResultSet r= stmt.executeQuery(query); 【4】 System.out.println("用户名"+" "+"密码:"); while(r.next()){ String r1=r.getString("ID"); String r2=r.getString("PWD"); System.out.println(" "+r1+" "+r2); } r.close(); stmt.close(); con.close();【5】
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 }catch (SQLException ex){ ex.printStackTrace(); } } } • 代码详解 • 建立Connection类的对象,并将其实例化,建立数据库的连接对象con。 • 建立Statement类的对象stmt,并在【5】处调用executeQuery ()方法,用于把 SQL 语句发送到 DBMS。
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 • 建立PreparedStatement 类的对象,并将其实例化,建立预编译SQL语句对象ps。 • 建立ResultSet rs类的对象rs,并在把其实例化,建立查询结果集。 • 分别关闭Connection类、Statement类、ResultSet rs类对象。 • 实现结果 run: 请输入用户名: bbb 请输入密码: 222
任务二 JDBC访问技术 子任务1 数据库表修改、插入和删除记录 知识导读 用户名 密码: aaa 111 bbb 222 生成成功。 打开数据库表LoginRecord,如下图8-10所示。 图8-10 数据库表LoginRecord
任务二 JDBC访问技术 子任务2 数据库表读取、查询和修改 知识导读 • 【案例】在数据源“login”的数据库“LoginRecord.mdb”中新建试题数据库表t1 • 设计要求如下:如上图8-11如示,(数据源设置同上),编写图形用户界面,有文本区和“读取”按钮,单击“读取”按钮会将数据库表t1中试题依次读入并显示在文本区中。 • 其中数据库表t1中数据项ID表示试题编号;数据项title 表示试题题目;数据项first 表示第一个选项内容;数据项second 表示第二个选项内容;数据项third 表示第三个选项内容;数据项fourth表示第四个选项内容;数据项result 表示正确答案。
任务二 JDBC访问技术 子任务2 数据库表读取、查询和修改 知识导读 • 完整的程序代码如下: import java.sql.*; import java.io.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; class EWindow extends Frame implements ActionListener{ JTextArea text; Button readButton;
任务二 JDBC访问技术 子任务2 数据库表读取、查询和修改 知识导读 Connection con; 【1】 Statement stmt; 【2】 ResultSet r; 【3】 String url="jdbc:odbc:login"; String query; int rid=0; EWindow(){ super("试题的读取"); text=new JTextArea(25,12); text.setFont(new Font("TimesRoman",Font.PLAIN,14));