1、单元员 22 使用 JDBC 更新数据库单元目标 掌握 JDBC 程序的结构及工作原理; 掌握 JDBC 纯 Java 驱动方式; 掌握如何使用 JDBC 获取数据库连接; 掌握运用 JDBC 对数据进行增、删、改。学习任务1.任务描述在员工管理系统中,需要建立员工表 emp,字段有员工编号(empno) 、姓名(ename) 、工作(job) 、经理编号(mgr) 、雇佣日期(hiredate)、工资(sal)、提成(comm)、部门编号(deptno),如图 5-23 所示。现要求使用 JDBC 连接数据库,能够根据员工编号查询、添加、修改、删除员工记录。图 5-23 员工表 emp 数据
2、示例2.运行结果员工数据管理程序设计知识准备22.1 JDBC 工作原理Sun 公司提供的 JDBC(Java Database Connectivity,Java 数据库连接技数据库连接技术术) ,是 Java 程序连接关系数据库的标准。JDBC 让程序员通过统一接口与不同数据库打交道,不必为每一种数据库编写不同的代码。JDBC 将数据库访问封装在类和接口中,程序员方便地对数据库进行增、删、改、查等操作。JDBC 框架结构包括四个组成部分,即 Java 应用程序、JDBC API 、JDBC DriverManager 和 JDBC 驱动程序。 应用程序调用统一的 JDBCAPI, 再由 J
3、DBCAPI通过 JDBC Driver Manager 装载数据库驱动程序,建立与数据库的连接,向数据库提交 SQL 请求,并将数据库处理结果 返回给 Java 应用程序。图 5-24 JDBC 框架结构JDBC 驱动程序有四类:1JDBC-ODBC 桥(JDBC-ODBC Bridge)将对 JDBC API 的调用,转为对 ODBC API 的调用,能够访问 ODBC 可以访问的所有数据库,但是,执行效率低、功能不够强大。Sun 建议开发中不使用这种免费的 JDBC-ODBC 桥驱动程序。2部分 Java、部分本机驱动程序(JDBC-NativeAPI Bridge)同样是一种桥驱动程序
4、。它将 JDBC 的调用转换成数据库厂商专用的 API,效率低,服务器易死机。不建议使用。员工数据管理程序设计3中间数据访问服务器(JDBC-Middleware)驱动程序独立于数据库,它只和一个中间层通信,由中间层实现多个数据库的访问。与前面两种不同的是,驱动程序不需要安装在客户端,而是安装在服务器端。4纯 Java 驱动程序(Pure JDBC Driver)纯 Java 驱动程序由数据库厂商提供,是最成熟的 JDBC 驱动程序,所有存取数据库的操作都直接由驱动程序完成,速度快,且又可跨平台。在开发中,推荐使用纯 Java 驱动程序。在 JDBC 框架结构中,供程序员编程调用的接口与类集成
5、在 java.sql 和javax.sql 包中,如 java.sql 包中常用的有 DriverManager 类、Connection 接口、Statement 接口和 ResultSet 接口。DriverManager 类根据数据库的不同,注册、载入相应的 JDBC 驱动程序, JDBC 驱动程序负责直接连接相应的数据库。Connection 接口负责连接数据库并完成传送数据的任务。Statement 接口由Connection 接口 产生,负责执行 SQL 语句,包括增、删、改、查等操作。ResultSet 接口负责保存 Statement 执行后返回的查询结果。图 5-25 常用接
6、口与类执行的关系22.2 JDBC 访问数据库JDBCAPI 完成三件事, 通过 Connection 接口建立与数据库连接, Statement接口执行 SQL 语句,ResultSet 接口处理返回结果。22.2.1 准备环境要想连接不同数据库,需要下载相应驱动程序,然后添加到当前工程中。比如, 连接 SQL Server 2008 数据库, 需准备 JDBC 驱动程序包 sqljdbc4.jar。然后, 在 Eclipse 中, 选中当前项目, 单击右键, 在菜单中选择属性 (Properties) ,打开配置对话框,选择 Java Build Path,选中 Libraries 标签,
7、单击 Add Jars 按钮,选择添加 sqljdbc4.jar 文件,将驱动程序包引入工程中。如图 5-26 所示:图 5-26 修改项目属性引入 sqljdbc4.jar 文件22.2.2 加载并注册驱动用 Class.forName()方法显示装载驱动程序。格式如下:tryClass.forName(JDBC 驱动程序类驱动程序类);/ 注册注册 JDBC 驱动驱动 catch (ClassNotFoundException e) / 处理异常处理异常System.out.println(无法找到驱动类无法找到驱动类);注解:1Class 类的 forName()方法以完整的 Java
8、类名字符串为参数,装载此类。此时将自动创建一个驱动类的实例,并自动调用驱动器管理器 DriverManager类中的 RegisterDriver 方法来注册它。2驱动类有可能不存在,使用此 Class.forName()方法就可能会抛出ClassNotFoundException 异常,因此需要捕获这个异常。比 如 : SQL Server2008数 据 库JDBC 驱 动 程 序 类 名 为com.microsoft.sqlserver.jdbc.SQLServerDriver,则对应加载驱动的代码为:tryClass.forName(com.microsoft.sqlserver.jdb
9、c.SQLServerDriver);/ 注册驱动 catch (ClassNotFoundException e) / 处理异常System.out.println(无法找到驱动类);22.2.3 Connection 对象Connection 对象与特定数据库的连接(会话) 。在连接上下文中执行 SQL语句并返回结果。标准方法是调用 DriverManager.getConnection()方法。格式如下:try / 用用 JDBCJDBC URLURL 标识数据库,建立数据库连接标识数据库,建立数据库连接Connection con=DriverManager.getConnection
10、(JDBC URL,数据库用数据库用户名户名, ,密码密码); catch (SQLException e) / 处理异常处理异常e.printStackTrace();注解:1JDBC URL 格式格式为:jdbc:子协议子协议:子名称子名称jdbc 表示协议,JDBC URL 中的协议总是 jdbc;子协议是驱动器名称;子名称是数据库的名称, 如果是位于远程服务器上的数据库, 则还应该包括网络地址。例如:连接本机 SQL Server2008 数据库服务器中 empmanage 数据库的 JDBCURL 书写为:jdbc:sqlserver:/localhost:1433;Database
11、Name=empmanage注解:jdbc表示协议,sqlserver是子协议,/localhost:1433;DatabaseName=empmanage 称为子名称。2 getConnection()方法第二个参数是访问数据库所需的用户名,第三个参数是用户密码。3 DriverManager.getConnection()方法在执行时可能会抛出 SQLException异常,因此需要捕获这个异常。22.2.4 Statement 对象Statement 对象用于执行静态 SQL 语句并返回所生成结果的对象。通过Connection 接口的 createStatement()方法可创建向数据
12、库发送 SQL 语句的Statement 对象。格式如下:try Statement stmt = con.createStatement(); / 发送发送 SQL 语句语句 catch (SQLException e) / 处理异常处理异常e.printStackTrace();executeUpdate()方法:用于执行 insert、update 或 delete 语句,以及 SQL语言中的 DDL 语句,例如 create table 等。例如,删除编号为 7369 的员工信息stmt.executeUpdate(delete from emp where empno=7369);e
13、xecuteUpdate()的返回值是一个整数,表示受影响的行数(即更新计数) ,例如修改了多少行、删除了多少行等。对于 create tabel 等语句,因不涉及行的操作,所以 executeUpdate()的返回值总为零。【注意】执行语句的所有方法都将关闭所调用的 Statement 对象当前打开的结果集 (如果存在) 。这意味着在重新执行 Statement 对象之前,需要完成对当前 ResultSet对象的处理。在 JDBC API 编写程序时,除使用 Statement 接口,还经常使用PreparedStatement接口编程。 PreparedStatement接口继承了Stat
14、ement接口。当执行 PreparedStatementpstmt=con.prepareStatement(SQL 语句);时, 表示不仅创建一个 PreparedStatement 对象,而且还要把 SQL 语句提交到数据库进行预编译, 作为提高性能的一条措施。 PreparedStatement 语句称为预编译语句。例如,现在要在 emp 表中增加一条记录,用 PreparedStatement 接口实现。/ 省略类的声明/ 准备 SQL 语句String sql= INSERT INTOemp(empno,ename,job,hiredate,sal,comm,deptno,mgr)
15、VALUES(?,?,?,?,?,?,?,?);PreparedStatement pstmt=con.prepareStatement(sql);/ 设置替代变量pstmt.setInt(1, emp.getEmpno();pstmt.setString(2, emp.getEname();员工数据管理程序设计pstmt.setString(3, emp.getJob();pstmt.setDate(4, new java.sql.Date(emp.getHiredate().getTime();pstmt.setDouble(5, emp.getSalary();pstmt.setDoub
16、le(6, emp.getCommision();pstmt.setInt(7, emp.getDeptno();pstmt.setInt(8, emp.getManagerno();/ 执行 SQL 语句num=pstmt.executeUpdate();/ 省略 JDBC 相关对象关闭操作经验:在应用中, 根据具体情况选用 PreparedStatement 接口或 Statement 接口。 但是,PreparedStatement 接口与 Statement 接口相比,有两个好处。一是,预编译语句是在执行 SQL 语句之前已编译好 SQL 语句, 而 Statement 的 SQL 语
17、句是当程序要执行时,才会去编译;二是,预编译语句中的 SQL 语句具有参数,每个参数用“?”替代。 “?”的值在执行之前利用 setXXX()方法设置。实际应用中,预编译提高 SQL 执行效率,建议尽量使用 PreparedStatement 接口。22.2.5 关闭数据库连接对象计算机资源是宝贵的,如果打开的资源太多,会造成内存缺失。虽然 Java提供垃圾回收机制,但是当内存达到一定程度,即使有垃圾回收机制,程序的运行效率也是非常低的。因此,当对象使用完成后,要关闭相关对象,让其释放占用的内存空间。关闭打开的各对象,该顺序与打开的顺序相反。需要依次关闭结果集对象、语句对象和连接对象。关闭语句
18、对象,代码为:stmt.close();关闭连接对象,代码为:con.close();这些语句操作过程中会抛出异常 SQLException,所以操作时需要进行异常处理。任务实施1.实现思路(1) 创建数据库以及数据表;(2) 编写实体类 Employee 实现员工数据的封装;(3) 编写 BaseDAO 类完成数据库连接、关闭等功能;(4) 编写 EmployeeDAO 类实现了员工表访问功能;(5) 编写 EmployeeBiz 模拟员工管理系统的业务操作。2.程序代码(1)创建数据库以及数据表本任务可采用不同数据库完成,我们在此以 SQL Server2008 为例。您可以使用 SQL
19、Server 的默认用户 sa 登录, 先创建一个数据库 empmanage, 并使用以下 SQL 语句创建 emp 表并为其添加几行测试数据。CREATE TABLE EMP(EMPNO INT CONSTRAINT PK_EMP PRIMARY KEY,-员工编号ENAME VARCHAR(10) NOT NULL,-姓名JOB VARCHAR(9),-工作MGR INT,-经理编号HIREDATE DATE,-雇佣日期SAL NUMERIC(7, 2),-工资COMM NUMERIC(7, 2),-提成DEPTNOINTCONSTRAINTFK_DEPTNOREFERENCESDEPT(
20、DEPTNO)-部门编号)GOINSERT INTO EMP VALUES(7369,SMITH,CLERK,7902,to_date(17-12-1980,dd-mm-yyyy),800,NULL,20);(2)编写实体类 Employee 实现员工数据的封装import java.util.Date;public class Employee 员工数据管理程序设计员工数据管理程序设计private String ename; / 员工姓名private String job; / 员工工作private int manager_no; / 员工的经理编号private Date hired
21、ate; / 员工参加工作的日期private double salary; / 员工的工资private double commision; / 员工的提成private int deptno; / 员工的部门编号private int empno; / 员工编号public Employee() public Employee(int empno, String ename, String job, int manager_no,Date hiredate, double salary, double commision, int deptno) / 给成员变量赋值/省略成员变量的 get
22、 方法、set 方法void show() System.out.println(empno + + ename + + job + +manager_no+ + hiredate + + salary + + + commision + + deptno);(3)编写 BaseDAO 类完成数据库连接、关闭等功能/省略相关类库的导入语句public class BaseDAO private static final String DRIVER_CLASS =com.microsoft.sqlserver.jdbc.SQLServerDriver;private static final S
23、tring DADABASE_URL =jdbc:sqlserver:/127.0.0.1:1433;DatabaseName= empmanage;private static final String DADABASE_USER = sa;private static final String DADABASE_PASSWORD = system;员工数据管理程序设计public static Connection getConnection()Connection con = null;tryClass.forName(DRIVER_CLASS);catch(ClassNotFoundE
24、xception ce)ce.printStackTrace();trycon =DriverManager.getConnection(DADABASE_URL,DADABASE_USER,DADABASE_PASSWORD);catch(SQLException e)e.printStackTrace();return con;public static void closeConnection(Connection con)tryif(con != null | !con.isClosed()con.close();catch(Exception e)e.printStackTrace(
25、);public static void closeResultSet(ResultSet rs)try if(rs != null) rs.close(); catch(Exception e) e.printStackTrace();public static void closeStatement(Statement stmt)try if(stmt != null) stmt.close(); catch(Exception e) e.printStackTrace();(4)编写 EmployeeDAO 类实现了员工表访问功能public class EmployeeDAO /* 查
26、询所有的员工信息*/public List getAllEmployees() List lEmployees = new ArrayList();Student stu = null;Connection con = null;Statement stmt = null;try /省略创建 Connection 对象和 Statement 对象String sqlStr = select * from emp;ResultSet rs = stmt.executeQuery(sqlStr);while (rs.next() Employee e = new Employee();e.setE
27、mpno(rs.getInt(empno);/省略给员工其他成员变量赋值语句e.show();lEmployees.add(e);BaseDAO.closeResultSet(rs);员工数据管理程序设计BaseDAO.closeStatement(stmt); catch (Exception e) e.printStackTrace(); finally BaseDAO.closeConnection(con);return lEmployees;/省略查询指定员工编号的员工信息/* 添加一个新的员工* param Employee 员工信息*/public int addEmployee
28、(Employee emp) int num = 0;Connection con = null;PreparedStatement pstmt = null;try con = BaseDAO.getConnection();String sqlStr = INSERT INTOemp(empno,ename,job,hiredate,sal,comm,deptno,mgr) VALUES(?,?,?,?,?,?,?,?);pstmt = con.prepareStatement(sqlStr);pstmt.setInt(1, emp.getEmpno();/省略给其他参数赋值num = p
29、stmt.executeUpdate();BaseDAO.closeStatement(pstmt); catch (Exception e) e.printStackTrace(); finally BaseDAO.closeConnection(con);return num;/省略删除指定员工编号的员工信息/省略更新制定员工的员工信息(5)编写 EmployeeBiz 模拟员工管理系统的业务操作public class EmployeeBiz public static void main(String args) EmployeeDAO dao = new EmployeeDAO();
30、dao.getAllEmployees();Calendar d = Calendar.getInstance();d.set(1973, 5, 29); / 设置日历为 1973 年 6 月 29 日Employee e = new Employee(1000, zxg, Manager, 7369,d.getTime(),2900, 300, 10);dao.addEmployee(e);e.setEname(zhuxg);dao.updateEmployee(e);dao.deleteEmployee(1000);任务拓展如果使用 Oracle 数据库并采用纯 Java 驱动程序连接数据
31、库,方法和步骤同连接 SQL Server 数据库基本相同。首先,准备好 Oracle 数据库 JDBC 驱动程序包 ojdbc14_g.jar。可以通过互联网去下载,也可以到 Oracle 的安装目录下去找,例如 OracleXE10g 安装在C:oraclexe下,那么ojdbc14_g.jar文件可以在C:oraclexeapporacleproduct10.2.0serverjdbclib 文件夹下找到。然后, 在配置 Build Path 对话框中, 选中 Libraries 标签, 添加 ojdbc14_g.jar文件,将驱动程序包引入工程中。最后,按照 JDBC 程序模板编写代码
32、,通过纯 Java 驱动方式与数据库建立员工数据管理程序设计连接。Oracle 数据库 JDBC 驱动程序类名为 oracle.jdbc.driver.OracleDriver,数据库JDBC URL 为 jdbc:oracle:thin:127.0.0.1:1521:xe, 其中 127.0.0.1 是数据库服务器的 IP 地址,1521 是监听器服务监听的端口号,xe 是在 Oracle 安装目录中的 tnsnames.ora 文件中配置的数据库服务名,这些都可以根据自己的实际情况进行修改。程序代码为:URL=jdbc:oracle:thin:127.0.0.1:1521:xe ;Clas
33、s.forName(oracle.jdbc.driver.OracleDriver);/加载、注册驱动程序Connection con = DriverManager.getConnection(URL,scott ,tiger);/建立数据库连接虽然不推荐使用 JDBC-ODBC 桥, 但是在开发小型系统与测试中, 仍然有人在用。例如,在用 Access 建立数据库表之后,先在控制面板进行 ODBC 数据源配置,获得数据源的名称 emp、用户名 sa 和密码 sasa。接着,编写代码,通过桥连方式与数据库建立连接。编写时,按照 JDBC 程序模板,设定 JDBC驱 动 程 序 类 和 JDB
34、C URL 。 JDBC-ODBC 桥 驱 动 程 序 类 名 为sun.jdbc.odbc.JdbcOdbcDriver , 数 据 源 名 称 为 emp , JDBC URL 为jdbc:odbc:emp。程序代码为:Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);/加载、注册驱动程序/建立数据库连接Connection con =DriverManager.getConnection(jdbc:odbc:emp,sa,sasa);比较使用不同数据库和不同类型的驱动程序在编程上的差别,主要是 JDBC驱动程序类和数据库 JDBC URL 不同,其他代码几乎不要修改。任务实训1.实训目的 掌握JDBC的工作原理; 掌握JDBC纯Java驱动方式; 掌握如何使用JDBC获取数据库连接; 掌握运用JDBC对数据进行增、删、改。2.实训内容编写一个用户维护的功能模块,在该模块中包括用户的注册、密码的更新、用户的注销(即删除) 。Users 数据表结构为:字段名数据类型是否允许为空备注idintnot null主键,标识列,表示用户 IDnamevarchar(50)not null用户名pwdvarchar(20)not null用户密码员工数据管理程序设计