应用程序 |
JDBC |
Oracle 驱动程序 |
Sybase 驱动程序 |
DB2 驱动程序 |
Informix 驱动程序 |
…… 驱动程序 |
JDBC API |
ODBC API |
JDBC-ODBC桥 |
ODBC层 |
数据源 |
Java应用程序 |
JDBC API |
厂商专有API |
JDBC驱动程序 |
数据源 |
Java应用程序 |
JDBC API |
JDBC驱动程序 |
本机驱动程序 |
数据源 |
Java应用程序 |
JDBC驱动程序 |
JDBC API |
JDBC驱动程序 |
数据源 |
Java应用程序 |
数据库名 | 驱动程序 | URL |
MS SQL Server 2000 | com.microsoft.jdbc.sqlserver.SQLServerDriver | Jdbc:Microsoft:sqlserver://[ip]:[port];user=[user];password=[password] |
JDBC-ODBC | sun.jdbc.odbc.JdbcOdbcDriver | jdbc:odbc:[odbcsource] |
Oracle oci8 | orcle.jdbc.driver.OracleDriver | jdbc.oracle:oci8:@[sid] |
Oracle thin Driver | oracle.jdbc.driver.OracleDriver | jdbd:oracle:thin:@[ip]:[port]:[sid] |
Cloudscape | com.cloudscape.core.JDBCDriver | jdbc:cloudscape:database |
MySQL | org.gjt.mm.mysql.Driver | jdbc:mysql:/ip/database,user,password |
第二节 JDBC核心类和接口 Driver接口 每个数据库驱动程序必须实现Driver接口。我们在编程中要连接数据库,必须先装载特定厂商提供的数据库驱动程序(Driver),驱动程序的装载方法如下: Class.forName(“<driver_class_name”>); DriverManager类 对于简单的应用程序,仅需要使用该类的方法getConnection,该方法将建立与数据库的连接。JDBC允许用户调用DriverManager类的方法getDriver、getDrivers和registerDriver及Driver类的方法connect,但在多数情况下,最好让DriverManager类管理建立连接的细节。 DriverManager类是JDBC的管理层,作用于用户和驱动程序之间,用于管理JDBC驱动程序。它跟踪可用的驱动程序,并在数据库和相应的驱动程序之间建立连接,另外,DriverManager类也处理诸如驱动程序登录时间限制及登录和跟踪消息的显示等事务。 作为初始化的一部分,DriverManager将试图装载系统属性“jdbc.drivers”所指的驱动程序类,这可以让用户定制在它们的应用程序中使用的JDBC驱动程序。例如,在Windows的HOME目录的/.hotjava/properties文件中,可以指定: Jdbc.drivers=<驱动程序> 另外,程序还可以显示的装载JDBC驱动程序。例如:下述代码用于装载my.sql.Driver Class.forName(“my.sql.Driver”); 在DriverManager中有一个非常重要的方法,就是getConnection(parameter),通过这个方法可以获得一个连接。 getConnection public static synchronized Connection getConnection(String url) 尝试建立一个和给定的URL的数据库连接,调用此方法时,DriverManager将在已注册的驱动中选择恰当的驱动来建立连接。 public static synchronized Connection getConnection(String url, Properties info) 与上类似,不过提供了一些属性,这些属性连接特定的数据库需要,至少包含user和password属性。 public static synchronized Connection getConnection(String url, String user,String password) 连接到指定URL的数据库,使用用户名为user,密码为password。 Connection接口 Connection对象代表与数据库的连接,也就是在已经加载的Driver和数据库之间建立连接。 连接过程包括所执行的SQL语句和在该连接上所返回的结果。一个应用程序可与单个数据库有一个或多个连接,或者可与许多数据库有连接。 close public void close() 关闭到数据库的连接,在使用完连接之后必须关闭,否则连接会保持一段比较长的时间,直到超时。 commit public void commit() 提交对数据库的更改,使更改生效。这个方法只有调用了setAutoCommit(false)方法后才有效,否则对数据库的更改会自动提交到数据库。 createStatement public Statement createStatement() throws SQLException public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException 创建一个Statement,Statement用于执行SQL语句。 prepareStatement public PreparedStatement prepareStatement(String sql) throws SQLException public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException 使用指定的SQL语句创建一个预处理语句,sql参数中往往包含一个或者多个“?”占位符。 Statement接口 一个Statement对象仅能有一个ResultSet对象。当完成对表的操作之后,必须重新得到另一个Statement对象,才能进行其他表的操作。 Statement对象可以用于执行一个静态的SQL语句,并得到SQL语句执行后的结果。 execute public boolean execute(String sql) throws SQLException 运行语句,返回是否有结果集。 executeQuery public ResultSet executeQuery(String sql) throws SQLException 运行查询语句,返回ResultSet对象。 executeUpdate public int executeUpdate(String sql) throws SQLException 运行更新操作,返回更新的行数。 PreparedStatement接口 PreparedStatement对象可以代表一个预编译的SQL语句,它从Statement接口继承而来,并与之有如下两方面的不同: u PreparedStatement实例包含已编译的SQL语句。 u 包含于PreparedStatement对象中的SQL语句可具有一个或多个IN参数。IN参数的值在SQL语句创建时未被指定。相反的,该语句为每个IN参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX方法来提供。 由于PreparedStatement对象已经预编译过,所以其执行速度要快于Statement对象。因此,需要多次执行的SQL语句经常创建为PreparedStatement对象,以提供效率。 作为Statement的子类,PreparedStatement继承了Statement的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代IN参数占位符的值。 另外,Statement接口中的三种方法execute、executeQuery和executeUpdate已经被更改,使之不再需要参数。 所有的setXXX方法的原型如下,其中XXX是与该参数相应的类型。例如,如果参数具有Java类型long,则使用的方法就是setLong。setXXX方法的第一个参数parameterIndex为要设置的参数的序数位置,第二个参数是设置给该参数的值。 setXXX public void setXXX(int parameterIndex, XXX x) throws SQLException 设定指定位置的参数值。 execute public boolean execute() throws SQLException 运行语句,返回是否有结果集。 executeQuery public ResultSet executeQuery() throws SQLException 运行查询语句,返回ResultSet对象。 executeUpdate public int executeUpdate() throws SQLException 运行更新操作,返回更新的行数。 ResultSet接口 ResultSet提供了对数据库中表的访问,一个ResultSet对象通常由执行一个Statement而生成。 ResultSet对象维护了一个光标指针,用来描述当前记录的位置,最初,光标指向第一个记录的位置之前,next方法将光标移到到下一个记录,其方法的原型如下。 boolean next() throws SQLException getXXX方法得到当前记录的字段的值,可以使用字段名或其索引得到自动的值,一般来说,使用字段的索引效率更高,字段的编号从1开始,1为当前记录的第一个字段,2为第二个字段,以此类推。 在ResultSet接口中,还有一系列的updateXXX方法,可以用来更新当前记录的字段值。 getXXX public XXX getXXX(int parameterIndex) throws SQLException public XXX getXXX(String columnName) throws SQLException 获取指定位置或者指定列的查询结果值。 第三节 JDBC编程实例 基本步骤 Ø 输入java.sql包 在程序的开头,必须加入下面的代码: Import java.sql.*; Ø 声明变量 在代码中,一般要声明三个相关的变量。Stmt用于SELECT语句,pstmt用于UPDATE语句,rs用于SELECT的结果集。 Statement stmt; PreparedStatement pstmt; ResultSet rs; Ø 加载jdbc驱动程序 Class.forName(“<jabc驱动程序>”); Ø 定义JDBC URL String url = “jdbc:odbc:oracle:thin@10.10.10.1:db9”; Ø 连接数据库 Connection conn = DriverManager.getConnection(url); Ø 进行相应的数据操作 根据需要创建Statement或PreparedStatement实例,执行SELECT操作或UPDATE操作。 Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2"); Ø 关闭数据库连接 conn.close(); 查询记录信息 Vector data = new Vector(); ResultSet rs = null; Statement stmt = null; Connection conn = null; //注册驱动器 try { //加载驱动程序 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //Class.forName("oracle.jdbc.driver.OracleDriver"); //得到数据库联接 conn= DriverManager.getConnection("jdbc:oracle:thin:@192.168.110.52:1521:edu","study","study"); //执行sql语句 stmt = conn.createStatement(); //返回数据集合 rs = stmt.executeQuery("select * from book where bookid=‘0007’"); while (rs.next()) { DataObject dataObject = new DataObject(); dataObject.setBookId(rs.getString("bookid")); dataObject.setBookName(rs.getString("bookname")); dataObject.setBookNumber(rs.getString("booknumber")); data.addElement(dataObject); } } catch (SQLException e1) { e1.printStackTrace(); } catch (ClassNotFoundException e) { System.out.println("Driver not found"); } //关闭联接 finally { try { rs.close(); stmt.close(); conn.close(); } catch (SQLException e2) { e2.printStackTrace(); } } 插入记录信息 String sql; Connection conn = null; PreparedStatement ps=null; //注册驱动器 try { //加载驱动程序 Class.forName("oracle.jdbc.driver.OracleDriver"); // 得到数据库联接 conn= DriverManager.getConnection("jdbc:oracle:thin:@192.168.110.52:1521:edu","study","study"); // 执行sql语句 sql="insert into book ( bookid,bookname,booknumber) values (?,?,?)"; ps = conn.prepareStatement(sql); ps.setString(1, "0021"); ps.setString(2, "数据库概论"); ps.setInt(3, 11); ps.executeUpdate(); } catch (SQLException e1) { e1.printStackTrace(); } catch (ClassNotFoundException e) { System.out.println("Driver not found"); } // 关闭联接 finally { try { ps.close(); conn.close(); } catch (SQLException e2) { e2.printStackTrace(); } } 更新记录信息 int state; Statement stmt = null; Connection conn = null; //注册驱动器 try { //加载驱动程序 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //Class.forName("oracle.jdbc.driver.OracleDriver"); //得到数据库联接 conn= DriverManager.getConnection("jdbc:oracle:thin:@192.168.110.52:1521:edu","study","study"); //执行sql语句 stmt = conn.createStatement(); //返回数据集合 state=stmt.executeUpdate("update book set booknumber=9 where bookname='java编程思想'"); if(state>0) { System.out.println("更新成功"); } else { System.out.println("更新失败"); } } catch(SQLException e1) { e1.printStackTrace(); } catch(ClassNotFoundException e) { System.out.println("Driver not found"); } //关闭联接 finally { try { stmt.close(); conn.close(); } catch(SQLException e2) { e2.printStackTrace(); } } 删除记录信息 boolean state=false; Statement stmt = null; Connection conn = null; //注册驱动器 try { //加载驱动程序 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //Class.forName("oracle.jdbc.driver.OracleDriver"); //得到数据库联接 conn= DriverManager.getConnection("jdbc:oracle:thin:@192.168.110.52:1521:edu","study","study"); //执行sql语句 stmt = conn.createStatement(); //返回数据集合 state=stmt.execute("delete from book where bookid='0007'"); if(state) { System.out.println("删除成功"); } else { System.out.println("删除失败"); } } catch (SQLException e1) { e1.printStackTrace(); } catch(ClassNotFoundException e) { System.out.println("Driver not found"); } //关闭联接 finally { try { stmt.close(); conn.close(); } catch (SQLException e2) { e2.printStackTrace(); } } 第四节 JDBC数据库连接池 在实际应用开发中,特别是在Web应用系统中,如果JSP、Servlet或EJB使用JDBC直接访问数据库中的数据,每一次数据访问请求都必须经历建立数据库连接、打开数据库、存取数据和关闭数据库连接等过程,而连接并打开数据库是一件既消耗资源又费时的工作,如果频繁的发生这种数据库操作,系统的性能必然会急剧的下降,甚至会导致系统崩溃。数据库连接池技术是解决这个问题最常用的方法,在许多应用程序服务器中,基本都提供了这项技术,无需自己编程。 数据库连接池技术的思想非常简单,将数据库连接作为对象存储在一个vector对象中,一旦数据库连接建立后,不同的数据库访问请求就可以共享这些连接,这样,通过复用这些已建立的数据库连接,可以克服上述缺点,极大的节省了系统资源和时间。 数据库连接池的主要操作如下: Ø 建立数据库连接池对象 Ø 按照事先指定的参数创建初始数量的数据库连接 Ø 对于一个数据库访问请求,直接从连接池中得到一个连接。如果数据库连接池对象中没有空闲的连接,且连接数没有达到最大,创建一个新的数据库连接 Ø 存取数据库 关闭数据库,释放所有数据库连接。