目录
- 什么是 JDBC?有什么用?
- JDBC 基础
- JDBC 接口
- JDBC 结果集
- 怎么用 JDBC?
什么是JDBC?有什么用?
Java Database Connectivity,Java数据库连接。用于执行SQL语句的Java API,包含一组与数据库通信的API,和与数据库通信的驱动程序。
当我们编程访问数据库的时候,是通过C语言 / C++语言直接访问数据库的接口。
对于不同数据库,就需要知道不同数据库对外提供的API,限制了程序扩展和跨平台实现。
- 优化:分层思想
只需要与最上层的接口进行交互,其它事项交给其他层进行处理。
- ODBC
Open Database Connect,开放数据库互联。
微软提出的应用程序与数据库交互的中间层。 - JDBC
Java提供的唯一的数据库交互接口。
JDBC为数据库开发人员提供了一个标准的API,据此可以构建更高级别的工具和接口,使数据库开发人员可以用纯Java API编写数据库应用程序。
JDBC基础
JDBC的构成
包含于Java的开发工具包(JDK),由三部分构成:
- 驱动程序管理器
使Java应用程序能正确的连接 JDBC驱动程序; - 驱动程序测试工具包
- JDBC-ODBC桥
使ODBC驱动程序可被用作JDBC驱动程序。
注:JDBC支持数据库访问的两层模型(客户机-数据库服务器) & 三层模型(客户机-业务逻辑服务器-数据库服务器)。
JDBC 驱动程序
1.JDBC-ODBC桥
注:从JDK1.8开始,已被移除。
2.本地 API 用 Java 来编写的驱动程序
3.JDBC 网络纯Java驱动程序
4.本地协议纯Java 驱动
MySQL 的 Connector/Java 的驱动程序是一个类型 4 驱动程序。因为他们的网络协议的专有性的,数据库厂商通常提供类型 4 的驱动程序。
通常情况下如果正在访问一个类型的数据库,如 Oracle,Sybase 或 IBM,首选驱动程序是类型 4。
如果 Java 应用程序同时访问多个数据库类型,类型 3 是首选的驱动程序。
第 2 类驱动程序是在类型 3 或类型 4 驱动程序还没有提供数据库的情况下显得非常有用。
类型 1 驱动程序不被认为是部署级别的驱动程序,它通常仅用于开发和测试目的。
JDBC连接数据库
导入驱动,注册驱动,数据库URL指定,创建连接对象。
-
导入 JDBC 驱动
-
注册 JDBC 驱动
将要使用的数据库的驱动类文件动态的加载到内存,然后才能连接数据库。- 方法1 Class.forName()
public class t{ public static void main(String[] args){ try{ Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { System.out.println("Error: unable to find driver class"); System.exit(1); } } }
- 方法2 DriverManager.registerDriver()
Driver driver = new com.mysql.jdbc.Driver(); DriverManager.registerDriver(driver);
-
数据库 URL 指定
加载驱动程序后,可以用DriverManager.getConnection()
方法连接数据库。
getConnection(String url);
getConnection(String url, Properties prop);
getConnection(String url, String user, String password);
注:常用数据库驱动程序名及数据库的 URL
RDBMS | JDBC 驱动程序的名称 | URL |
---|---|---|
Mysql | com.mysql.jdbc.Driver | jdbc:mysql://hostname/databaseName |
Oracle | oracle.jdbc.driver.OracleDriver | jdbc:oracle:thin:@hostname:port Number:databaseName |
DB2 | COM.ibm.db2.jdbc.net.DB2Driver | jdbc:db2:hostname:port Number/databaseName |
Sybase | com.sybase.jdbc.SybDriver | jdbc:sybase:Tds:hostname: port Number/databaseName |
- 创建连接对象
以Mysql为例。
// 1. 使用数据库 URL 的用户名和密码
String URL = "jdbc:mysql://localhost/EXAMPLE";
String USER = "username";
String PASS = "password";
Connection conn = DriverManager.getConnection(URL, USER, PASS);
// 2. 只用一个数据库 URL
String URL = "jdbc:mysql://localhost/EXAMPLE?user=root&password=0909";
Connection conn = DriverManager.getConnection(URL);
// 3. 用数据库 URL 和一个 Properties 对象
import java.util.*;
String URL = "jdbc:mysql://localhost/EXAMPLE";
Properties pro = new Properties();
// Properties对象保存一组关键字对
pro.put("user", "root");
pro.put("password", "");
Connection conn = DriverManager.getConnection(URL, pro);
// 关闭 JDBC
conn.close();
JDBC 接口
接口 | 应用场景 |
---|---|
Statement | 当在运行时使用静态 SQL 语句时(Statement 接口不能接收参数) |
CallableStatement | 当要访问数据库中的存储过程时(CallableStatement 对象的接口还可以接收运行时输入参数) |
PreparedStatement | 当计划多次使用 SQL 语句时(PreparedStatement 接口接收在运行时输入参数) |
- Statement
// 使用前,先创建Statement对象
Statement stmt = null;
try {
stmt = conn.createStatement();
...
} catch (SQLException e) {
...
} finally {
// 应该明确关闭Statement对象,确保正确的清除
stmt.close();
}
Statement对象的方法 | 说明 |
---|---|
boolean execute(String SQL) | 如果 ResultSet 对象可以被检索返回布尔值 true,否则返回 false。使用这个方法来执行 SQL DDL 语句,或当需要使用真正的动态 SQL |
int executeUpdate(String SQL) | 用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQLDDL(数据定义语言)语句。返回值是一个整数,指示受影响的行数(即更新计数) |
ResultSet executeQuery(String SQL) | 返回 ResultSet 对象。用于产生单个结果集的语句,例如 SELECT 语句 |
- PreparedStatement
扩展了Statement接口,可多次执行 SQL 语句。
PreparedStatement pstmt = null;
try {
// JDBC 中,所有参数都将被 ? 代表
String SQL = "UPDATE Student SET age = ? WHERE id = ?";
pstmt = conn.preparedStatement(SQL);
// setXXX() 方法将值绑定到参数
// XXX 表示希望绑定到输入参数值的 Java 数据类型
pstmt.setXXX(x1, x2);
} catch (SQLException e){
...
} finally {
pstmt.close();
}
- CallableStatement
为 DBMS 提供了以标准形式调用存储过程的方法。
参数 | 描述 |
---|---|
IN | 它的值是在创建 SQL 语句时未知的参数,将 IN 参数传给 CallableStatement 对象是通过 setXXX() 方法完成的 |
OUT | 其值由它返回的 SQL 语句提供的参数。从 OUT 参数的 getXXX() 方法检索值 |
INOUT | 同时提供输入和输出值的参数,绑定的 setXXX() 方法的变量,并使用 getXXX() 方法检索值 |
注:PreparedStatement
对象只使用 IN 参数。CallableStatement
对象可使用3个。
// 调用存储过程的语法
{call 存储过程名 [(?, ?, ...)]}
// 返回结果参数的过程
{ ? = call 存储过程名 [(?, ?, ...)]}
// 不带参
{ call 存储过程名 }
// 创建 CallableStatement 对象
// Connection 的方法 prepareCall
CallableStatement cstmt = null;
try {
String SQL = "{call getEXAMPLEName (?, ?)}";
cstmt = conn.prepareCall(SQL);
...
} catch (SQLException e) {
...
} finally {
cstmt.close();
}
JDBC 结果集
- ResultSet
执行查询数据库语句后生成的数据表。
ResultSet 对象具有指向当前数据行的光标。最初光标位于第一行之前,next
方法使光标移动到下一行,当无下一行时,返回false。
默认的 ResultSet 是不可更新的,只能迭代一次。
ResultSet 对象的方法:- 导航
移动光标; - 获取
查看光标当前行的数据; - 更新
更新光标当前行的数据;
- 导航
// 通过下面连接方法来创建所需的 ResultSet 结果集
// RSType --- ResultSet 对象的类型
// RSConcurrency --- ResultSet常量,指定结果集为只读 / 可更新
createStatement(int RSType, int RSConcurrency);
prepareStatement(String SQL, int RSType, int RSConcurrency);
prepareCall(String SQL, int RSType, int RSConcurrency);
ResultSet 的类型,如果不指定 ResultSet 类型,将自动获得一个是 TYPE_FORWARD_ONLY:
类型 | 描述 |
---|---|
ResultSet.TYPE_FORWARD_ONLY | 游标只能向前移动的结果集 |
ResultSet.TYPE_SCROLL_INSENSITIVE | 游标可以向前和向后滚动,但不及时更新,就是如果数据库里的数据修改过,并不在 ResultSet 中反应出来 |
ResultSet.TYPE_SCROLL_SENSITIVE | 游标可以向前和向后滚动,并及时跟踪数据库的更新,以便更改 ResultSet 中的数据 |
并发性的 ResultSet,如果不指定任何并发类型,将自动获得一个为 CONCUR_READ_ONLY
并发 | 描述 |
---|---|
ResultSet.CONCUR_READ_ONLY | 创建结果集只读。这是默认的 |
ResultSet.CONCUR_UPDATABLE | 创建一个可更新的结果集 |
初始化一个 Statement 对象来创建一个 ResultSet 对象:
try {
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATEABLE);
} catch (Exception e) {
...
} finally {
...
}
怎么用
如何编写一个JDBC程序?
1、导入 JDBC 驱动
// linux
// wget http://labfile.oss.aliyuncs.com/courses/110/mysql-connector-java-5.1.47.jar
2、打开连接。DriverManager.getConnection();
3、执行查询。
4、从结果集提取数据。ResultSet.get();
5、清理资源。明确的关闭所有数据库资源,释放内存。
import java.sql.*;
public class JdbcTest {
// JDBC 驱动器名称 和数据库地址
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
//数据库的名称为 EXAMPLE
static final String DB_URL = "jdbc:mysql://localhost/EXAMPLE";
// 数据库用户和密码
static final String USER = "root";
static final String PASS = "";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try{
//注册 JDBC 驱动程序
Class.forName(JDBC_DRIVER);
//打开连接
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//执行查询
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql = "SELECT id, name, age FROM Students"; // select * ..
ResultSet rs = stmt.executeQuery(sql);
//得到和处理结果集
while(rs.next()){
//检索
int id = rs.getInt("id");
int age = rs.getInt("age");
String name = rs.getString("name");
//显示
System.out.print("ID: " + id);
System.out.print(", Age: " + age);
System.out.print(", Name: " + name);
System.out.println();
}
//清理环境
rs.close();
stmt.close();
conn.close();
}catch(SQLException se){
// JDBC 操作错误
se.printStackTrace();
}catch(Exception e){
// Class.forName 错误
e.printStackTrace();
}finally{
//这里一般用来关闭资源的
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}
}
System.out.println("Goodbye!");
}
}
// javac -cp .:mysql-connector-java-5.1.47.jar JdbcTest.java
// java -cp .:mysql-connector-java-5.1.47.jar JdbcTest