JDBC 全拼是什么?
Java DataBase Connectivity
JDBC 是什么?
JDBC 是 Java 语言中用于连接和操作数据库
的API。
JDBC 是如何连接数据库的?
“连接数据库”,即获取数据库连接对象
。
首先,获得特定数据库的 JDBC 驱动。
// MySQL 示例
Class.forName("com.mysql.jdbc.Driver");
// Oracle 示例
Class.forName("oracle.jdbc.driver.OracleDriver");
然后,使用 DriverManager.getConnection()
方法建立连接:
// MySQL 连接示例
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "password";
Connection connection = DriverManager.getConnection(url, username, password);
// Oracle 连接示例
String url = "jdbc:oracle:thin:@localhost:1521:orcl";
Connection connection = DriverManager.getConnection(url, username, password);
这样,我们就完成了使用 JDBC 连接数据库的步骤。
注意事项:
- 需要添加数据库驱动依赖(如MySQL的mysql-connector-java)
- 实际项目中应该将数据库配置信息放在配置文件中
- 考虑使用连接池(如HikariCP)管理数据库连接
- 对于复杂应用,建议使用DAO模式或ORM框架(如MyBatis、Hibernate)
JDBC 相关的核心接口和类有哪些?
JDBC 自带
的核心接口和类:
Driver 接口
DriverManager 类
Connection 接口
Statement 接口
、PreparedStatement 接口
、CallableStatement 接口
ResultSet 接口
与 JDBC 相关
的核心接口和类:
SQLException 类
DataSource 接口
Statement、PreparedStatement、CallableStatement
之间有什么区别?
Statement 接口
、PreparedStatement 接口
、CallableStatement 接口
,都是 JDBC 中,用于执行SQL语句
的接口,而PreparedStatement 接口
、CallableStatement 接口
都是Statement 接口
的子接口。
它们的区别主要在使用场景
上。
Statement 接口
是最基本
的 SQL 语句执行接口,它每次执行
时都会将SQL语句发送到数据库进行编译,这也导致它容易造成SQL 注入
的问题。
为防止 SQL 注入问题,就需要使用PreparedStatement接口
来执行 SQL 语句,因为它会对SQL 语句进行预编译
,使用参数化查询
,提高效率的同时,也更加安全。
而CallableStatement 接口
则专用于调用数据库存储过程
,支持输入(IN)、输出(OUT)和输入输出(INOUT)参数,可以处理复杂的返回值。
总结:
- 优先使用PreparedStatement,因为它安全且高效
- 只有在调用存储过程时才使用CallableStatement
- 避免使用Statement,除非是执行非常简单的静态SQL
Statement 示例:
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
PreparedStatement 示例:
PreparedStatement pstmt = conn.prepareStatement(
"SELECT * FROM users WHERE username = ? AND password = ?");
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
CallableStatement示例:
CallableStatement cstmt = conn.prepareCall("{call get_employee_data(?, ?)}");
cstmt.setInt(1, employeeId); // 设置输入参数
cstmt.registerOutParameter(2, Types.VARCHAR); // 注册输出参数
cstmt.execute();
String result = cstmt.getString(2); // 获取输出参数
JDBC 的使用步骤是什么?
JDBC 的使用,大概分为六个步骤
:
-
使用
Class.forName()
加载数据库驱动。 -
通过
DriverManager.getConnection()
获取连接。 -
使用
Connection
创建Statement
对象。 -
通过
Statement
或PreparedStatement
执行SQL语句。 -
使用
ResultSet
处理查询结果。 -
close()
方法依次关闭ResultSet
、Statement
和Connection
。
示例代码:
import java.sql.*;
public class JdbcExample {
public static void main(String[] args) {
// 数据库连接信息
String url = "jdbc:mysql://localhost:3306/your_database";
String username = "your_username";
String password = "your_password";
// 使用 try-with-resources 自动关闭资源
try (Connection conn = DriverManager.getConnection(url, username, password);
// 创建预编译Statement,防止SQL注入
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
) {
// 1. 设置查询参数
pstmt.setInt(1, 1001); // 查询ID为1001的用户
// 2. 执行查询
try (ResultSet rs = pstmt.executeQuery()) {
// 3. 处理结果集
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println("ID: " + id);
System.out.println("Name: " + name);
System.out.println("Email: " + email);
}
}
// 4. 执行更新操作示例
try (PreparedStatement updateStmt = conn.prepareStatement(
"UPDATE users SET name = ? WHERE id = ?")) {
updateStmt.setString(1, "John Doe");
updateStmt.setInt(2, 1001);
int rowsAffected = updateStmt.executeUpdate();
System.out.println("更新了 " + rowsAffected + " 行数据");
}
} catch (SQLException e) {
// 处理数据库异常
System.err.println("数据库操作出错:");
e.printStackTrace();
}
}
}
excute、excuteQuery、excuteUpdate的区别是什么?
excute、excuteQuery、excuteUpdate
三者的区别,主要在适用的SQL类型和返回值
两个方面。
在适用的SQL类型
上,excute()
方法适用于任何类型的 SQL 语句
,excuteQuery()
则专用于 SELECT 语句
。excuteUpdate()
则专用于 INSERT、UPDATE、DELETE 等DML语句和 CREATE TABLE 等 DDL 语句
。
而在返回值
上,excute()
方法的返回值是boolean
类型;excuteQuery()
的返回值是ResultSet
对象,表示查询的结果集
;excuteUpdate()
的返回值则是int
类型,代表受影响的行数
。
execute()
示例:
boolean hasResultSet = stmt.execute(sql);
if (hasResultSet) {
ResultSet rs = stmt.getResultSet();
// 处理结果集
} else {
int updateCount = stmt.getUpdateCount();
// 处理更新计数
}
executeQuery()
示例:
ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
while (rs.next()) {
// 处理每一行数据
}
executeUpdate()
示例:
int rowsAffected = stmt.executeUpdate("UPDATE employees SET salary = salary + 1000");
System.out.println("更新了 " + rowsAffected + " 行记录");
excute()
的返回值为 true 和 false 时分别是什么含义?
true:执行的是查询语句
(SELECT),有结果集
返回。
false:执行的是更新语句
(INSERT, UPDATE, DELETE等)或无结果集
的语句。
executeUpdate()
执行 DDL 语句时,返回值是多少?
执行 DDL (数据定义语言)语句如 CREATE TABLE时,返回值为0
。
因为执行 DDL 语句时,没有影响到任何数据行,所以返回值为 0。
注意 | |
---|---|
executeUpdate | 执行 DDL (数据定义语言)语句如 CREATE TABLE时,返回值为0 。 |
什么是事务的 ACID 特性?
原子性(Atomicity) | 事务中的所有操作要么全部完成,要么全部不执行 |
---|---|
一致性(Consistency) | 事务执行前后数据库保持一致状态 |
隔离性(Isolation) | 并发事务之间互不干扰 |
持久性(Durability) | 事务提交后结果永久保存,事务执行前后,数据库状态一致 |
JDBC 事务管理的核心方法有哪些?
方法 | 作用 |
---|---|
connection.setAutoCommit(false); | 开启事务,关闭自动提交 |
connection.commit(); | 提交事务,使所有操作永久生效 |
connection.rollback(); | 回滚事务,撤销所有未提交的操作 |
Savepoint savepoint = connection.setSavepoint("savepoint1"); | 设置保存点,可以通过conn.rollback(savepoint); 回滚到特定保存点 |
JDBC 是如何进行事务管理的?
JDBC完整事务处理示例:
Connection conn = null;
try {
// 1. 获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
// 2. 关闭自动提交,开启事务
conn.setAutoCommit(false);
// 3. 执行SQL操作
Statement stmt = conn.createStatement();
stmt.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1");
stmt.executeUpdate("UPDATE accounts SET balance = balance + 100 WHERE user_id = 2");
// 4. 提交事务
conn.commit();
System.out.println("事务执行成功");
} catch (SQLException e) {
// 5. 发生异常时回滚
if (conn != null) {
try {
conn.rollback();
System.out.println("事务回滚");
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
// 6. 恢复自动提交并关闭连接
try {
if (conn != null) {
conn.setAutoCommit(true); // 恢复自动提交模式
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
如何获得“数据库驱动连接对象”?
connection
是通过数据库驱动获得的连接对象:
Connection connection = DriverManager.getConnection(url, user, password);
JDBC 如何设置事务隔离级别
JDBC 支持设置不同的事务隔离级别:
// 设置隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
// 可用的隔离级别常量:
// TRANSACTION_READ_UNCOMMITTED
// TRANSACTION_READ_COMMITTED (最常用)
// TRANSACTION_REPEATABLE_READ
// TRANSACTION_SERIALIZABLE
为什么要使用数据库连接池?
数据库连接池能帮助我们管理数据库连接、提高性能和节省资源
。
数据库连接池可以分配、管理和释放数据库连接
,同时,因为连接是数据库连接池预先建立的,所以使用时可以直接获取,不需要等待连接创建
,从而节省了创建连接的时间和资源,也省去了频繁关闭连接的消耗。而频繁的创建和关闭连接是非常消耗资源和时间的。
作用 | 备注 |
---|---|
连接复用 | 连接已预先建立,使用时直接获取,无需等待连接创建 |
性能提升 | 减少连接创建时间,频繁的创建和关闭连接是非常耗时的。 |
数据库连接管理 | 分配、管理和释放数据库连接,提供连接生命周期管理、超时检测等功能 |
常见的数据库连接池有哪些?
常见的数据库连接池有:Druid
、C3P0
、DBCP
等。
Druid 数据库连接池如何使用?
首先,需要导入 jar 包,并引入 Druid 数据库连接池的依赖。
步骤 | ||
---|---|---|
1 | 导入 jar 包:druid-1.0.9\druid-1.0.9.jar | |
2 | 编写配置文件,放在 src 目录下 | |
3 | 修改url,用户名和密码 | |
4 | 通过 Properties 集合加载配置文件 | |
5 | 通过 Druid 连接池工厂类获取数据库连接池对象 | |
6 | 获取数据库连接进行使用 | |
注意 | Druid 不会自动加载配置文件,需要我们手动加载,但是文件的名称可以自定义。 |
如何自定义数据库连接池?
步骤 |
---|
定义一个类,实现 DataSource 接口。 |
定义一个容器,用于保存多个 Connection 连接对象。 |
定义静态代码块,通过 JDBC 工具类获取 10 个连接保存到容器中。 |
重写 getConnection 方法,从容器中获取一个连接并返回。 |
定义 getSize 方法,用于获取容器的大小并返回。 |