读书人

《partner4java 叙说JDBC》之第一步:

发布时间: 2012-11-26 11:48:49 作者: rapoo

《partner4java 讲述JDBC》之第一步:JDBC基础
JDBC的作用:
The Java Database Connectivity (JDBC) 是一套Java API,用于Java编程语言和广泛的数据库之间连接的标准。JDBC API提供了一套访问“SQL数据库”的调用级API。


JDBC API概述:
JDBC API做的三件事情:
1、建立与数据库的连接(或访问系统数据源)
2、发送SQL语句
3、处理结果


JDBC架构:
JDBC API包括两部分接口:
第一部分是JDBC API提供给应用开发者(也就是我们这些码农);
第二部分是底层的JDBC驱动API,需JDBC驱动开发者实现。

如图:

《partner4java 叙说JDBC》之第一步:JDBC基础

左侧 -- 这种风格的驱动程序将JDBC调用 直接转换成 数据库管理系统使用的网络协议,通过Intranet访问直接从客户机调用DBMS服务器。
右侧 -- 这种风格的驱动程序将JDBC调用由一个中间件服务器,将其转换为DBMS协议,由中间件提供到不同的数据库的连接。


JDBC的优势:
使用现有的数据库 -- 使用JDBC技术,企业不会锁定任何专有的架构,可以很容易继续使用已安装的数据库。
简化企业开发 -- Java API和JDBC API结合,使得应用开发更容易和“廉价”。复杂的数据库访问任务被隐藏在JDBC之下,且JDBC API简单易学、易于部署。
网络计算机不需要配置 -- 使用JDBC API,不需要在客户端上做任何配置。所需的全部信息以JDBC URL或DataSource对象形式定义,通过Java编写的驱动程序进行链接。



本章内容分为下两大部分:
第一部分:HelloWorld简单示例
第二部分:JDBC详解




第一部分:HelloWorld简单示例



准备环境导入相关JDBC驱动(我这里用的是MySQL):
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>


一个基本的JDBC操作大体分为四步:
第一步:注册驱动
第二步:新建数据库连接
第三步:创建 用于执行静态SQL语句并返回它所生成结果 的对象
第四步:执行SQL 、获取返回结果并遍历

(希望你看完每一步讲解,自己动手完成一下)


第一步:注册驱动
向 DriverManager 注册给定驱动程序(可以注册多个不同的驱动程序)。

(1)为什么要注册驱动程序:
为了与特定的数据源相连,JDBC必须加装相应的驱动程序。
当获取连接时,DriverManager会试图从已注册的JDBC驱动程序集中选择一个适当的驱动程序。

(2)涉及到的两个类:
com.mysql.jdbc.Driver:
每个驱动程序类必须实现的接口。核心方法connect(String url, Properties info) 主要用于实现建立与数据库连接的底层协议。

javaw.sql.DriverManager:
管理一组 JDBC 驱动程序的基本服务。用来处理装载驱动程序并为创建新的数据库连接提供支持。

(3)如何操作
以MySQL为例:Class.forName("com.mysql.jdbc.Driver");
MySQL中你会遇到有些代码中注册的驱动不同:Class.forName("org.gjt.mm.mysql.Driver");
两者区别:
org.gjt.mm.mysql.Driver只是老版本遗留,为了兼容没有删除:
看下org.gjt.mm.mysql.Driver实现便知:
package org.gjt.mm.mysql;import java.sql.SQLException;public class Driver extends com.mysql.jdbc.Driver{}

(4)为什么这么注册
两点解释:
1、Class.forName -- 调用 forName("X") 将导致命名为 X 的类被初始化。这里的初始化为静态初始化。
2、看我们的com.mysql.jdbc.Driver
public class Driver extends NonRegisteringDriver implements java.sql.Driver { static  {     try     {       DriverManager.registerDriver(new Driver());     } catch (SQLException E) {       throw new RuntimeException("Can't register driver!");     }   } }


第二步:新建数据库连接
(1)涉及到的新类:
java.sql.Connection:
完成对某一指定数据库连接功能;与特定数据库的连接(会话);在连接上下文中执行 SQL 语句并返回结果。
Connection 对象的数据库能够提供描述其表、所支持的 SQL 语法、存储过程、此连接功能等等的信息。

(2)如何操作:分为三步
1、Connection conn = DriverManager.getConnection(url, user, password);
2、捕获意外 -- 在建立连接和对数据库进行操作的过程中,都可能产生意外。在JDBC中经常遇到的意外是SQLException。
3、关闭连接 -- conn.close(); 对于任何一个连接,当不再对数据源进行操作时,应该将其关闭。

(3)操作解释:
DriverManager类的getConnection方法用于建立与某个数据源的连接。
试图建立到给定数据库 URL 的连接。DriverManager 试图从已注册的 JDBC 驱动程序集中选择一个适当的驱动程序。
若连接成功,则返回一个Connection类的对象。以后对这个数据源的操作都是基于这个Connection对象。
getConnection方法是DriverManager类中的静态方法,所以使用时不用生成DriverManager类的对象,直接使用类名DriverManager调用就可以了。

参数:
url - jdbc:subprotocol:subname 形式的数据库 url
(如:jdbc:mysql://localhost:3306/jdbc_test
jdbc:mysql:对于MySQL来说是固定的协议格式;localhost为host;3306为数据库连接端口;jdbc_test为具体操作库名)
user - 数据库用户,连接是为该用户建立的
password - 用户的密码

Demo:
public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/jdbc_test";String user = "root";String password = "123456";Connection conn = null;try {// 加载 驱动程序Class.forName("com.mysql.jdbc.Driver");// 试图建立到给定数据库 URL 的连接。DriverManager 试图从已注册的 JDBC 驱动程序集中选择一个适当的驱动程序。conn = DriverManager.getConnection(url, user, password);System.out.println(conn);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}finally{if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}


第三步:创建 用于执行静态SQL语句并返回它所生成结果 的对象
(1)相关对象
java.sql.Statement:
用于执行静态 SQL 语句并返回它所生成结果的对象。
Statement对象主要用于一般查询语句的执行,要想执行一个SQL查询语句,必须首先建立Statement对象。

(2)如何操作:和我们Connection操作类似
1、创建Statement对象 Connection.createStatement()方法用于建立一个Statement对象。
2、捕获异常
3、关闭Statement -- 每一个Statement对象在使用完毕后,都应该关闭。st.close();
立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作。一般来说,使用完后立即释放资源是一个好习惯,这样可以避免对数据库资源的占用。

Demo:
public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/jdbc_test";String user = "root";String password = "123456";Connection conn = null;Statement st = null;try {// 加载 驱动程序Class.forName("com.mysql.jdbc.Driver");// 试图建立到给定数据库 URL 的连接。DriverManager 试图从已注册的 JDBC 驱动程序集中选择一个适当的驱动程序。conn = DriverManager.getConnection(url, user, password);// 创建一个 Statement 对象来将 SQL 语句发送到数据库。st = conn.createStatement();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (st != null) {st.close();}} catch (SQLException e) {e.printStackTrace();} finally {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}}


第四步:执行SQL 、获取返回结果并遍历(万事俱备只欠东风)
(1)执行查询语句
设计的新类:
java.sql.ResultSet:
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
ResultSet对象包括一个由查询语句返回的一个表,这个表中包含所有的查询结果。对ResultSet对象的处理必须逐行进行,而对每一行中的各个列,可以按任何顺序进行处理。

简单操作方式:
// 执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。
ResultSet rs = st.executeQuery("select * from user");

操作详解:
在Statement对象上,可以使用executeQuery方法来执行一个查询语句。executeQuery参数是一个String对象,即一个SQL的SELECT语句。
它的返回值是一个ResultSet类的对象。
在默认情况下,同一时间每个 Statement 对象在只能打开一个 ResultSet 对象,如果再次获获取会自动关闭上一个打开的ResultSet对象。

(2)遍历返回值 分为两步:
1、遍历
ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。
while (rs.next()) {

}
2、获取遍历光标当前行数据
ResultSet类的getXXX方法可以从某一列中获得结果。其中XXX是JDBC中的Java数据类型,如getString,getDate等。
getXXX方法接收一个指定要检索列的参数。
有两种指定列的方法:一种是以一个int值作为第几列的索引( 第一个列是 1,第二个列是 2,…… ),另一种是以一个String作为列名来索引(使用 SQL AS 子句指定的列标签。如果未指定 SQL AS 子句,则标签是列名称 )。

while (rs.next()) {
System.out.println(rs.getString("username"));
System.out.println(rs.getString("password"));
}

在对每一行进行处理时,可以对各个列按任意顺序进行处理。
不过,按从左至右的顺序对各列进行处理可以获得较高的执行效率。

数据转换:
ResultSet类的getXXX方法视图将结果集中的SQL数据类型转换为它所返回的Java数据类型。
如果使用getXXX方法去读取一个SQL NULL值,可能有以下几个情形:
1)返回为Java Object的getXXX方法将返回Java null值。
2)getByte,getShort,getInt,getLong,getFloat和getDouble将返回零值。
3)getBoolean将返回false值。

数据类型转换表:
java类型SQL类型
booleanBIT
byteTINYINT
shortSMALLINT
intINTEGER
longBIGINT
StringCHAR,VARCHAR,LONGVARCHAR
byte arrayBINARY,VAR BINARY
java.sql.DateDATE
java.sql.TimeTIME
java.sql.TimestampTIMESTAMP

(3)关闭Statement相关
关闭 Statement 对象时,还将同时关闭其上获取的 ResultSet 对象(如果有)。

Demo:
public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/jdbc_test";String user = "root";String password = "123456";Connection conn = null;Statement st = null;try {// 加载 驱动程序Class.forName("com.mysql.jdbc.Driver");// 试图建立到给定数据库 URL 的连接。DriverManager 试图从已注册的 JDBC 驱动程序集中选择一个适当的驱动程序。conn = DriverManager.getConnection(url, user, password);// 创建一个 Statement 对象来将 SQL 语句发送到数据库。st = conn.createStatement();// 执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。ResultSet rs = st.executeQuery("select * from user");// 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。// ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在// ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。while (rs.next()) {// 在对每一行进行处理时,可以对各个列按任意顺序进行处理。// 不过,按从左至右的顺序对各列进行处理可以获得较高的执行效率。System.out.println(rs.getString("username"));System.out.println(rs.getString("password"));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (st != null) {st.close();}} catch (SQLException e) {e.printStackTrace();} finally {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}}



第二部分:JDBC详解


先提出几个问题:
1、执行executeQuery获取的ResultSet,ResultSet进行了关闭是否还可以遍历获取数据?
(几种情况会引起ResultSet关闭:1、自身主动关闭;2、Statement关闭)


2、数据库服务器关闭后ResultSet是否还可以遍历?(也就是说)


3、Connection关闭后ResultSet是否还可以遍历?


(自己动手写个Demo试一下,然后想一起能推断出来什么)


我们接下来的内容主要分为以下7块:
1、Statement两个重要子接口;
2、获取结果集的信息;
3、更新数据库操作;
4、输入参数;
5、事务;
6、批量执行。




1、Statement两个重要子接口

java.sql.Statement:
在一个给定的连接中作为SQL执行声明的容器,它包含了两个重要的子类型:
PreparedStatement:用于执行预编译的SQL声明;
CallableStatement:用于执行数据库中存储过程的调用;


PreparedStatement:
Statement对象在每次执行SQL语句时都将该语句传递给数据库,在多次执行同一语句时,这样效率很低。
这时可以使用PreparedStatement对象。如果数据库支持预编译,SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。

(1)创建PreparedStatement对象
从一个Connection对象可以创建一个PreparedStatement对象。在创建时,应该给出要预编译的SQL语句:
PreparedStatement ps = conn.prepareStatement("select * from user");

(2)执行查询语句
PreparedStatement对象也使用executeQuery方法来执行语句。与Statement类不同的是该方法没有参数。
这是由于创建PreparedStatement对象时,已经给出了要执行的SQL语句,并进行了预编译。
ResultSet rs = ps.executeQuery();
上诉语句可以被执行多次,无需重新给出SQL语句。

(3)关闭PreparedStatement
PreparedStatement对象也是使用close方法来关闭的,且也是必须关闭。

Demo:

public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/jdbc_test";String user = "root";String password = "123456";Connection conn = null;PreparedStatement ps = null;try {Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection(url, user, password);ps = conn.prepareStatement("update user set money = ? where id = ?");ps.setDouble(1, 10);ps.setInt(2, 1);ps.addBatch();ps.setDouble(1, 10);ps.setInt(2, 2);ps.addBatch();ps.executeBatch();} catch (Exception e) {e.printStackTrace();} finally {try {if (ps != null) {ps.close();}} catch (SQLException e) {e.printStackTrace();} finally {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}}



读书人网 >其他数据库

热点推荐