JDBC简介

JDBC简介

DBC是什么?

​ 由于数据库的厂商有很多,例如MySQL,Oracle等厂商,数据可能来自多个数据库或者我们需要切换数据库,DBC就是为了降低数据库与应用之间的耦合度而诞生的,下图是没有DBC的示意图:

无DBC

​ 下图为有DBC(JDBC)的示意图,JDBC API相对于JDBC Driver Manager来说为更高级的模块:

JDBC应用框架

JDBC的意义

  • ODBC(Open Data Base Connectivity)是使用最广的、用于访问关系数据库的编程接口,它能在几乎所有平台上连接几乎所有的数据库,ODBC不适合直接在Java中使用,因为ODBC API是C的库函数,在Java程序中调用本地C代码有比较大的局限性,如安全性、健壮性、可移植性等;从ODBC C API到Java API的字面翻译是不可取的,例如Java没有指针而ODBC却对指针用得很广泛

  • JDBC(Java Database Connectivity)是Java平台中用于连接和操作数据库的标准应用程序编程接口(API)。它允许Java应用程序与各种不同类型的关系型数据库进行交互,执行SQL语句、处理结果集、管理数据库连接和事务等操作

JDBC的使用:

​ JDBC的使用主要分为三步:

  • 建立与数据库的连接

    • 加载JDBC驱动程序
    • 建立与数据库的连接
  • 执行SQL语句

    • 在数据库连接上创建Statement对象,将各种SQL语句发送到所连接的数据库执行
    • 对于多次执行但参数不同的SQL语句,可以使用PreparedStatement对象
    • 可以使用CallableStatement对象调用数据库上的存储过程
  • 处理结果集

    • 结果集是查询语句返回的数据库记录的集合
    • 在结果集中通过游标(cursor)控制具体记录的访问
    • SQL数据类型与Java数据类型的转换—— 根据SQL数据类型的不同,使用不同的方法读取数据
    • 关闭数据库连接

更详细的解释:

加载驱动程序:

加载的方式有两种:

  1. 从系统属性java.sql中读取Driver的类名,并一一注册。

  2. 程序中使用Class.forName()方法动态装载并注册Driver,如:

1
2
3
4
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver")
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
Class.forName("oracle.jdbc.driver.OracleDriver")
Class.forName("com.mysql.jdbc.Driver")

建立数据库连接:

​ 通过DriverManager.getConnection()与数据库建立连接

1
public static Connection getConnection(String url, String user, String password) throws SQLException

url 是数据库连接串,指定数据库访问协议以及数据源。一般格式:jdbc:<subprotocol>:<subname>

例:通过 JDBC-ODBC 桥接驱动与 wombat 数据源建立连接

1
Connection con = DriverManager.getConnection("jdbc:odbc:wombat", "myUsername", "myPassword");

Statement对象

​ 在数据库连接上创建 Statement 对象,将各种SQL语句发送到所连接的数据库执行

1
2
public ResultSet executeQuery(String sql) throws SQLException
public int executeUpdate(String sql) throws SQLException

例子:传送SQL语句并得到结果集 rs

1
2
Statement stmt = con.createStatement( );
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");

PreparedStatement

  • 由方法 prepareStatement 所创建

  • PreparedStatement对象用于发送带有一个或多个输入参数(IN参数)的SQL语句。PreparedStatement拥有一组方法,用于设置IN参数的值。执行语句时,这些IN参数将被送到数据库中。PreparedStatement的实例扩展了 Statement,因此它们都包括了 Statement 的方法。PreparedStatement对象有可能比Statement对象的效率更高,因为它已被预编译过并存放在那以供将来使用

JDBC的层次结构

  • DriverManager 角色:事实上,一般我们操作 Driver,获取 Connection 对象都是交给 DriverManager 统一管理的。DriverManger 可以注册和删除加载的驱动程序,可以根据给定的 url 获取符合 url 协议的驱动 Driver 或者是建立 Conenction 连接,进行数据库交互

  • Drive 角色:驱动加载进内存,其实就是实现了Java.sql.Driver接口的类。比如使用Class.forName()将对应的驱动类加载到内存中,然后执行内存中的 static 静态代码段,代码段中,会创建一个驱动Driver的实例,放入 DriverManager 中,供 DriverManager 使用

  • Connection 角色:表示与特定数据库的连接(建立数据通信通道),可以获取到数据库的一些信息,包括:其表信息,应该支持的SQL语法,数据库内有什么存储过程,此链接功能的信息等等

  • Statement 角色:根据传入的 sql 语句,将其整理组合成数据库能够识别的 sql 语句,然后传递 sql 请求,之后会得到返回的结果。对于查询 sql,结果会以 ResultSet 的形式返回

  • ResultSet 角色:查询 sql 执行后,会得到 ResultSet 对象,作为数据库结果的映射。ResultSet 对从数据库返回的结果进行了封装,使用迭代器的模式逐条取出结果集中的记录(假如是 List,大数据库的情况下会直接撑爆)

代码示例解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.sql.*;

public class JdbcTest {
public static void main(String args[]) {

String url= "jdbc:mysql://localhost/test";
Connection con;
String sql;
Statement stmt;
String num,name,sex;
int age,math,eng,spec;

try {
Class.forName("com.mysql.jdbc.Driver");
} catch(java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}

try {
con = DriverManager.getConnection(url, "root", "java"); //
stmt = con.createStatement();

//向student表中插入一行记录。
sql = "INSERT INTO STUDENT " +
"VALUES('200108','赵小龙','男',20,71,62,76)";
stmt.executeUpdate(sql);

//检索student表中的所有记录并获取数据输出。
sql = " SELECT * FROM STUDENT";
ResultSet rs = stmt.executeQuery(sql);
System.out.println("学号 姓名 性别 年龄"+
" 高等数学 英语 专业课");
while(rs.next()){
num = rs.getString(1);
name = rs.getString(2);
sex = rs.getString(3);
age = rs.getInt(4);
math = rs.getInt(5);
eng = rs.getInt("英语");
spec = rs.getInt("专业课");
System.out.println(num+" "+name+" "+sex+" "+age+" "+math
+" "+eng+" "+spec);
}

//检索高等数学成绩80分以上的学生信息。
rs = stmt.executeQuery("SELECT 学号,姓名,高等数学,英语,专业课 "+
"FROM STUDENT "+
"WHERE 高等数学>=80" );
System.out.println();
System.out.println("The students whose math mark is beyond 80 are:");
while(rs.next()){
num = rs.getString(1);
name = rs.getString(2);
math = rs.getInt(3);
eng = rs.getInt("英语");
spec = rs.getInt("专业课");
System.out.println("学号="+num+" "+"姓名="+name+" "+"高等数学="+
math+" "+"英语="+eng+" "+"专业课="+spec);
}

//关闭连接。
stmt.close();
con.close();
} catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
}
}
  • 初始化数据库URL、连接对象(Connection)、SQL语句(Statement),以及用于存储查询结果的变量
1
2
3
4
5
6
String url= "jdbc:mysql://localhost/test";
Connection con;
String sql;
Statement stmt;
String num,name,sex;
int age,math,eng,spec;
  • 使用Class.forName()加载并注册MySQL JDBC驱动
1
2
3
4
5
6
try {
Class.forName("com.mysql.jdbc.Driver");
} catch(ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
  • 获取数据库连接,创建Statement对象,并执行SQL语句向STUDENT表中插入一条记录
1
2
3
4
5
6
7
try {
con = DriverManager.getConnection(url, "root", "java");
stmt = con.createStatement();

// 插入学生记录
sql = "INSERT INTO STUDENT VALUES('200108','小张','男',20,71,62,76)";
stmt.executeUpdate(sql);
  • 执行SQL查询获取STUDENT表中的所有记录,并打印所有学生信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 查询并打印所有学生记录
sql = "SELECT * FROM STUDENT";
ResultSet rs = stmt.executeQuery(sql);
// 输出表头
System.out.println("学号 姓名 性别 年龄"+
" 高等数学 英语 专业课");
while(rs.next()){
// 从结果集中提取字段值
num = rs.getString(1); // 学号
name = rs.getString(2); // 姓名
sex = rs.getString(3); // 性别
age = rs.getInt(4); // 年龄
math = rs.getInt(5); // 数学成绩
eng = rs.getInt("英语"); // 英语成绩
spec = rs.getInt("专业课"); // 专业课成绩
// 打印学生信息
System.out.println(num+" "+name+" "+sex+" "+age+" "+math
+" "+eng+" "+spec);
}
  • 执行SQL查询获取数学成绩超过80分的学生信息,并打印这些学生的记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
         // 查询数学成绩大于等于80分的学生
rs = stmt.executeQuery("SELECT 学号,姓名,高等数学,英语,专业课 "+
"FROM STUDENT "+
"WHERE 高等数学>=80" );
System.out.println("\nThe students whose math mark is beyond 80 are:");

// 遍历迭代器
while(rs.next()){
// 从结果集中提取字段值
num = rs.getString(1); // 学号
name = rs.getString(2); // 姓名
math = rs.getInt(3); // 数学成绩
eng = rs.getInt("英语"); // 英语成绩
spec = rs.getInt("专业课"); // 专业课成绩
// 打印符合条件的学生信息
System.out.println("学号="+num+" "+"姓名="+name+" "+"高等数学="+
math+" "+"英语="+eng+" "+"专业课="+spec);
}
  • 关闭Statement和Connection以释放资源。
1
2
3
4
5
6
7
8
            // 关闭连接和Statement
stmt.close();
con.close();
} catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
}
}