目录
JDBC是Java DataBase Connectivity的缩写,它提供了一种使用Java语言操作关系型数据库的方法。通过JDBC,我们可以使用Java程序连接和操纵数据库,进行数据的增删改查操作。
JDBC架构
JDBC由两个部分组成,即JDBC API和JDBC驱动程序。JDBC API提供了Java程序连接和操纵数据库的标准API,JDBC驱动程序实现了JDBC API定义的接口,用于连接和操作特定数据库。
应用程序层
应用程序层是最高层,它包含了应用程序中的Java代码,可以通过JDBC API访问数据库。
主要包括以下三个部分:
DriverManager:驱动管理器是JDBC API的入口点,它负责管理和加载所有可用的数据库驱动程序。
Connection:连接是JDBC API中与数据库进行通信的核心接口,它代表了一个数据库连接。
Statement:语句是JDBC API中用于执行SQL语句的接口,它可以执行查询和更新操作。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcExample {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 加载MySQL驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 获取数据库连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");
// 创建Statement对象
stmt = conn.createStatement();
// 执行查询
rs = stmt.executeQuery("SELECT * FROM users");
// 处理查询结果
while (rs.next()) {
System.out.println(rs.getString("name") + " " + rs.getInt("age"));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC API层
JDBC API层是应用程序层和JDBC驱动程序之间的接口,它提供了一组标准的接口,使得应用程序可以与各种不同的数据库进行通信,无需了解底层数据库的实现细节。
JDBC API层是指JDBC提供的一组接口,用于访问数据库和执行SQL语句。这些接口包括:
-
DriverManager:提供了一组方法来管理数据库驱动程序和创建连接。
-
Connection:表示应用程序和数据库之间的连接。
-
Statement:用于执行静态SQL语句并返回结果。
-
PreparedStatement:是Statement的子类,可以使用参数化查询来提高性能和安全性。
-
CallableStatement:是PreparedStatement的子类,可以执行存储过程。
-
ResultSet:表示SQL查询的结果集。
import java.sql.*; public class JdbcDemo { static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost:3306/mydb"; static final String USER = "root"; static final String PASS = "password"; public static void main(String[] args) { Connection conn = null; Statement stmt = null; try{ // 注册 JDBC 驱动 Class.forName(JDBC_DRIVER); // 打开连接 System.out.println("连接数据库..."); conn = DriverManager.getConnection(DB_URL,USER,PASS); // 创建表 System.out.println("创建表..."); stmt = conn.createStatement(); String sql = "CREATE TABLE STUDENTS " + "(ID INTEGER not NULL, " + " NAME VARCHAR(255), " + " AGE INTEGER, " + " PRIMARY KEY ( ID ))"; stmt.executeUpdate(sql); // 插入数据 System.out.println("插入数据..."); sql = "INSERT INTO STUDENTS " + "VALUES (100, 'Tom', 20)"; stmt.executeUpdate(sql); // 查询数据 System.out.println("查询数据..."); sql = "SELECT * FROM STUDENTS"; ResultSet rs = stmt.executeQuery(sql); // 输出结果 while(rs.next()){ int id = rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); System.out.print("ID: " + id); System.out.print(", Name: " + name); System.out.println(", Age: " + age); } // 关闭连接 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!"); } }
驱动程序管理层
驱动程序管理层负责管理和加载JDBC驱动程序,它将JDBC API调用转换为适当的数据库调用,然后将结果返回给应用程序层。
作用是封装底层数据库连接的复杂性,向上层提供统一的接口,使得上层应用程序可以使用相同的方式来访问不同的数据库,提高应用程序的可移植性和灵活性。
数据库管理系统层
数据库管理系统层是最底层,它包含了实际的数据库,负责处理JDBC驱动程序发送的请求,并返回结果。
JDBC驱动程序
JDBC驱动程序分为四种类型,即JDBC-ODBC桥接驱动程序、本地API驱动程序、网络协议驱动程序和本地协议驱动程序。
有两种类型的JDBC驱动程序:
-
Type 1驱动程序:也称为JDBC-ODBC桥接驱动程序,它将JDBC API的调用转换为ODBC调用,并由ODBC驱动程序将这些调用传递到底层数据库。这种驱动程序的优点是简单易用,但它的性能较差。
-
Type 4驱动程序:也称为本地协议驱动程序,它直接将JDBC API的调用转换为底层数据库的调用,不需要任何中间件。这种驱动程序的优点是性能好,但它的实现比较复杂。
JDBC连接
在使用JDBC操作数据库之前,需要先建立与数据库的连接。JDBC提供了Connection接口用于建立与数据库的连接,通常需要提供数据库的URL、用户名和密码等信息。
连接数据库需要以下几个步骤:
- 加载数据库驱动程序
- 创建一个数据库连接
- 创建一个
java.sql.Statement
对象 - 执行SQL查询
- 处理查询结果
- 关闭连接和释放资源
import java.sql.*; public class JdbcExample { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { // 加载MySQL驱动程序 Class.forName("com.mysql.jdbc.Driver"); // 创建数据库连接 String url = "jdbc:mysql://localhost:3306/mydb"; String user = "root"; String password = "password"; conn = DriverManager.getConnection(url, user, password); // 创建Statement对象 stmt = conn.createStatement(); // 执行SQL查询 String sql = "SELECT * FROM books"; ResultSet rs = stmt.executeQuery(sql); // 处理查询结果 while (rs.next()) { String title = rs.getString("title"); String author = rs.getString("author"); double price = rs.getDouble("price"); System.out.println(title + " by " + author + " - $" + price); } // 关闭连接和释放资源 rs.close(); stmt.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }
JDBC语句
JDBC提供了Statement接口和PreparedStatement接口用于执行SQL语句。Statement接口是基本的执行SQL语句的接口,PreparedStatement接口可以预编译SQL语句,提高了执行效率。
主要有以下几种类型:
-
DDL语句:Data Definition Language,用于定义数据结构,包括CREATE、ALTER和DROP等。
-
DML语句:Data Manipulation Language,用于对数据进行增、删、改和查操作,包括INSERT、UPDATE、DELETE和SELECT等。
-
DCL语句:Data Control Language,用于定义访问权限和控制数据的访问,包括GRANT、REVOKE等。
-
TCL语句:Transaction Control Language,用于控制事务的提交和回滚,包括COMMIT和ROLLBACK等。
String sql = "SELECT * FROM users WHERE id = ?"; PreparedStatement stmt = conn.prepareStatement(sql); stmt.setInt(1, 1); ResultSet rs = stmt.executeQuery(); while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println("id: " + id + ", name: " + name + ", age: " + age); }
JDBC结果集
JDBC提供了ResultSet接口用于访问执行SQL语句所返回的结果集。ResultSet接口提供了诸如获取列值、移动指针等方法。
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String email = resultSet.getString("email");
System.out.println("User: id = " + id + ", name = " + name + ", email = " + email);
}
} catch (SQLException e) {
e.printStackTrace();
}
JDBC事务
JDBC提供了Transaction接口用于管理事务。事务可以保证一组操作要么全部成功,要么全部失败。JDBC事务的处理方式可以使用自动提交和手动提交两种方式。手动提交需要程序员显式地调用commit方法提交事务。
在JDBC中,事务处理是通过Connection对象来实现的。JDBC支持以下事务隔离级别:
-
TRANSACTION_NONE:表示没有事务支持。
-
TRANSACTION_READ_UNCOMMITTED:表示允许脏读、幻读和不可重复读。
-
TRANSACTION_READ_COMMITTED:表示避免了脏读,但允许幻读和不可重复读。
-
TRANSACTION_REPEATABLE_READ:表示避免了脏读和不可重复读,但允许幻读。
-
TRANSACTION_SERIALIZABLE:表示避免了所有的并发问题,但性能最差。
在JDBC中,可以通过以下方法来处理事务:
-
setAutoCommit(boolean autoCommit):用于指定是否自动提交事务。
-
commit():用于提交当前事务。
-
rollback():用于回滚当前事务。
事务处理过程的典型流程为:
-
调用Connection对象的setAutoCommit(false)方法,禁用自动提交事务。
-
在事务中执行多个SQL语句。
-
如果所有SQL语句都执行成功,调用Connection对象的commit()方法提交事务。
-
如果其中任何一个SQL语句执行失败,调用Connection对象的rollback()方法回滚事务,恢复到事务开始之前的状态。
Connection conn = null; try { conn = DriverManager.getConnection(DB_URL, USER, PASS); conn.setAutoCommit(false); // 禁用自动提交事务 // 执行多个SQL语句 conn.commit(); // 提交事务 } catch (SQLException e) { if (conn != null) { conn.rollback(); // 回滚事务 } } finally { if (conn != null) { conn.close(); // 关闭连接 } }