Java Web 之 JDBC 100问

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 连接数据库的步骤。

注意事项:

  1. 需要添加数据库驱动依赖(如MySQL的mysql-connector-java)
  2. 实际项目中应该将数据库配置信息放在配置文件中
  3. 考虑使用连接池(如HikariCP)管理数据库连接
  4. 对于复杂应用,建议使用DAO模式或ORM框架(如MyBatis、Hibernate)

JDBC 相关的核心接口和类有哪些?

JDBC 自带的核心接口和类:

  1. Driver 接口
  2. DriverManager 类
  3. Connection 接口
  4. Statement 接口PreparedStatement 接口CallableStatement 接口
  5. ResultSet 接口

与 JDBC 相关的核心接口和类:

  1. SQLException 类
  2. DataSource 接口

Statement、PreparedStatement、CallableStatement 之间有什么区别?

Statement 接口PreparedStatement 接口CallableStatement 接口,都是 JDBC 中,用于执行SQL语句的接口,而PreparedStatement 接口CallableStatement 接口都是Statement 接口的子接口。

它们的区别主要在使用场景上。

Statement 接口最基本的 SQL 语句执行接口,它每次执行时都会将SQL语句发送到数据库进行编译,这也导致它容易造成SQL 注入的问题。

为防止 SQL 注入问题,就需要使用PreparedStatement接口来执行 SQL 语句,因为它会对SQL 语句进行预编译,使用参数化查询,提高效率的同时,也更加安全。
CallableStatement 接口则专用于调用数据库存储过程,支持输入(IN)、输出(OUT)和输入输出(INOUT)参数,可以处理复杂的返回值。

总结:

  1. 优先使用PreparedStatement,因为它安全且高效
  2. 只有在调用存储过程时才使用CallableStatement
  3. 避免使用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 的使用,大概分为六个步骤

  1. 使用Class.forName()加载数据库驱动。

  2. 通过DriverManager.getConnection()获取连接。

  3. 使用Connection创建Statement对象。

  4. 通过StatementPreparedStatement执行SQL语句。

  5. 使用ResultSet处理查询结果。

  6. close()方法依次关闭ResultSetStatementConnection

示例代码:

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

为什么要使用数据库连接池?

​ 数据库连接池能帮助我们管理数据库连接、提高性能和节省资源

​ 数据库连接池可以分配、管理和释放数据库连接,同时,因为连接是数据库连接池预先建立的,所以使用时可以直接获取,不需要等待连接创建,从而节省了创建连接的时间和资源,也省去了频繁关闭连接的消耗。而频繁的创建和关闭连接是非常消耗资源和时间的。

作用备注
连接复用连接已预先建立,使用时直接获取,无需等待连接创建
性能提升减少连接创建时间,频繁的创建和关闭连接是非常耗时的。
数据库连接管理分配、管理和释放数据库连接,提供连接生命周期管理、超时检测等功能

常见的数据库连接池有哪些?

常见的数据库连接池有:DruidC3P0DBCP等。

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 方法,用于获取容器的大小并返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值