当前位置: 首页 > news >正文

Java的JDBC编程

目录

1. JDBC工作原理

各部分自身理解

2.JDBC使用

2.1 环境配置

2.2 创建

2.3 连接

2.4 构造

2.5 发送需求

2.6 释放资源

2.7 使用问题自身理解

2.7.1 创建

a.为什么使用向下转型

b.一大段的代码是什么意思

c.用户和密码是什么

2.7.2 连接

a.如何选择Connection类型

b.connection常见的错误

2.7.3 构造

a.为什么使用PreparedStatement

b.异常的区分

c.为什么使用statementc

2.7.4 发送需求

a. 选择哪一个exe方法

b. 为什么要int n

2.7.5 释放资源

a. 为什么要释放资源

2.8 增加功能

2.8.1 总流程代码

2.8.2 能否自己输入

2.9 删除功能

2.10 修改功能

2.11 查找功能

如何进行方式使用

什么是ResultSet对象

3.总代码及其理解

3.1 增删改

3.2查找

4.扩展问题(重点)

1. 数据库连接有哪些方式?分别有什么区别

1. JDBC直接连接

2. 数据库连接池(Connection Pool)

3. ORM框架(如Hibernate/MyBatis)

4. JPA(Java Persistence API)

5. 分布式数据库连接

加分点

常使用的三种主要方式

1. 直接连接(像每次叫快递都重新打电话)

2. 连接池(像小区里的快递柜)

3. ORM框架(像代购服务)

常见简单问题

1. 为什么不要用直接连接?

2. ORM框架会慢吗?

3. 连接池参数怎么设置?

2. 数据库Statement和PreparedStatement有什么区别?

1. 核心区别总结

2. 逐项详解

(1) SQL构造方式

(2) 预编译机制

(3) 安全性对比

(4) 性能差异(批量插入10万条数据测试)

3. 加分点

(1) 预编译底层原理

(2) 为什么PreparedStatement能防SQL注入?

(3) 适用场景选择

5.总结:JDBC与数据库操作(快递生活版)

一、核心要点回顾

二、技术选型建议

1.小白起步

2.进阶开发

3.高并发

三、避坑指南

1.绝对不要做

2.必须要做


1. JDBC工作原理

各部分自身理解

(快递站进行比喻)

1.应用层:打开手机APP下单(就像用户点击按钮)

2.程序员开发:APP根据你的操作生成订单(程序员写代码实现功能)

3.JDBC 接口层:快递公司提供的标准包装盒(Sun公司制定的统一规则)

4.JDBC 驱动层:快递员(不同数据库厂商的"翻译员")

5.数据库:仓库货架(最终存储数据的地方)

整个过程就像:你下单→APP打包请求→用标准包装盒装好→交给对应快递公司→最终存到仓库

2.JDBC使用

2.1 环境配置

2.2 创建

2.3 连接

2.4 构造

2.5 发送需求

2.6 释放资源

2.7 使用问题自身理解

2.7.1 创建

a.为什么使用向下转型

b.一大段的代码是什么意思

c.用户和密码是什么

2.7.2 连接

a.如何选择Connection类型

b.connection常见的错误

2.7.3 构造

a.为什么使用PreparedStatement

b.异常的区分

c.为什么使用statementc

2.7.4 发送需求

a. 选择哪一个exe方法

b. 为什么要int n

2.7.5 释放资源

a. 为什么要释放资源

(用完的快递盒要回收,否则家里会堆满垃圾)

2.8 增加功能

2.8.1 总流程代码

2.8.2 能否自己输入

2.9 删除功能

2.10 修改功能

2.11 查找功能

如何进行方式使用

什么是ResultSet对象

就像快递员拿给你的包裹清单,需要用next()逐个查看

3.总代码及其理解

3.1 增删改

3.2查找

 

4.扩展问题(重点)

1. 数据库连接有哪些方式?分别有什么区别

数据库连接方式主要有JDBC直连、连接池、ORM框架、JPA和分布式连接。

JDBC直连适合简单场景但性能差;

连接池通过复用连接提升高并发性能;

Hibernate/MyBatis用ORM简化开发,但Hibernate适合复杂对象模型,MyBatis更灵活;

JPA是标准规范;

分布式连接解决分库分表问题。

1. JDBC直接连接

  • 原理:通过DriverManager每次创建新的物理连接,操作完成后立即关闭。

  • 特点

    • 优点:实现简单,适合小型项目或测试场景。

    • 缺点:频繁创建/销毁连接开销大,性能低,不适合高并发。

  • 代码示例

    Connection conn = DriverManager.getConnection(url, user, password);
    // 执行SQL...
    conn.close(); // 直接关闭

2. 数据库连接池(Connection Pool)

  • 原理:预先创建并维护一组连接,使用时从池中获取,用完归还而非关闭。

  • 常见实现:HikariCP、Druid、C3P0、DBCP。

  • 特点

    • 优点:复用连接,减少资源开销,支持并发和高性能场景。

    • 缺点:需要配置参数(如最大连接数、超时时间),维护成本稍高。

  • 核心参数

    • maxPoolSize:最大连接数(防资源耗尽)

    • idleTimeout:空闲连接回收时间

3. ORM框架(如Hibernate/MyBatis)

  • 原理:封装JDBC,通过对象关系映射(ORM)操作数据库。

  • Hibernate

    • 全自动ORM,通过实体类映射表结构,支持HQL。

    • 优点:开发效率高,适合复杂对象模型。

    • 缺点:SQL透明性低,复杂查询优化困难。

  • MyBatis

    • 半自动ORM,通过XML/注解配置SQL与对象映射。

    • 优点:灵活控制SQL,适合复杂查询场景。

    • 缺点:需手动编写SQL,维护成本较高。

4. JPA(Java Persistence API)

  • 原理:Java EE标准ORM规范,Hibernate是其主要实现。

  • 特点

    • 强调通过注解定义实体关系(如@Entity@OneToMany)。

    • 提供EntityManager统一接口,支持跨数据库移植。

  • 适用场景:需要标准化、避免厂商锁定的企业级应用。

5. 分布式数据库连接

  • 场景:分库分表、读写分离、微服务多数据源。

  • 实现方式

    • ShardingSphere:通过代理或SDK实现分片路由。

    • Spring AbstractRoutingDataSource:动态切换数据源。

  • 核心挑战:事务一致性、跨库查询聚合。

加分点

  1. 连接池工作原理

    • 初始化时创建minIdle个连接备用。

    • 请求到达时,优先分配空闲连接,无空闲且未达maxPoolSize则新建。

    • 归还连接时标记为空闲而非关闭,超时未用则回收。

  2. ORM的N+1查询问题

    • 场景:查询主表后循环查询关联子表(如SELECT * FROM User后循环查Order)。

    • 优化:Hibernate中通过@BatchSizeJOIN FETCH提前加载。

  3. 事务管理

    • 强调连接池与事务管理器(如Spring @Transactional)的集成。

    • 分布式场景下可提及Seata等分布式事务解决方案。

常使用的三种主要方式

1. 直接连接(像每次叫快递都重新打电话)
  • 原理:每次操作数据库都新建一个连接,用完立刻关闭。

  • 比喻:就像每次寄快递都重新打电话叫快递员上门,效率低。

  • 缺点:频繁开关连接效率低,就像每次都让快递员跑一趟。

// 1. 加载驱动(告诉快递公司你要用哪家快递)
Class.forName("com.mysql.jdbc.Driver");

// 2. 直接连接(打电话叫快递员)
Connection conn = DriverManager.getConnection(
    "jdbc:mysql://localhost:3306/test", // 数据库地址
    "root",  // 用户名(快递柜管理员)
    "123456" // 密码(快递柜密码)
);

// 3. 执行SQL(让快递员取件)
Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO users(name) VALUES('张三')");

// 4. 关闭连接(快递员离开)
stmt.close();
conn.close();
2. 连接池(像小区里的快递柜)
  • 原理:提前创建一批连接,用完放回池子里,下次直接用。

  • 比喻:小区里的快递柜,快递员提前放好包裹,你随时取用。

  • 优点:复用连接,性能高,适合多人使用。

// 1. 配置连接池参数(设置快递柜大小)
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
config.setUsername("root");
config.setPassword("123456");
config.setMaximumPoolSize(10); // 最多10个连接(快递柜最多存10个包裹)

// 2. 创建连接池(安装快递柜)
HikariDataSource dataSource = new HikariDataSource(config);

// 3. 从池中获取连接(开柜取包裹)
Connection conn = dataSource.getConnection();

// 4. 执行SQL(使用包裹)
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users");
ResultSet rs = pstmt.executeQuery();

// 5. 归还连接(用完放回快递柜)
rs.close();
pstmt.close();
conn.close(); // 实际是放回池中,不是真关闭

3. ORM框架(像代购服务)
  • 原理:不用写SQL,用对象操作数据库。

  • 比喻:像找代购帮你买东西,你只要说需求,代购自己处理细节。

  • 优点:不用写繁琐的SQL,适合复杂业务。

// 2. 直接调用方法(让代购帮你拿)
SqlSession session = sqlSessionFactory.openSession();
User user = session.selectOne("UserMapper.getUser", 1);
session.close();

常见简单问题

1. 为什么不要用直接连接?
  • 答案:就像每次网购都让快递员单独跑一趟,费时费力。连接池相当于让快递员批量送货到快递柜,你随时取用。

2. ORM框架会慢吗?
  • 答案:就像代购可能比你自己买慢一点,但省去了你跑腿的时间。大多数场景下够用,特别复杂的查询可以混合使用SQL。

3. 连接池参数怎么设置?
  • 经验值

config.setMaximumPoolSize(10);  // 根据你的服务器CPU核心数设置,比如CPU是4核,设置4~8
config.setConnectionTimeout(30000); // 等快递柜超时时间30秒

2. 数据库StatementPreparedStatement有什么区别?

Statement和PreparedStatement的核心区别在于SQL构造方式和安全性。

Statement通过字符串拼接SQL,存在注入风险且性能低;

PreparedStatement使用参数化查询,预编译提升性能并防止注入。

例如,用户登录时,PreparedStatement会将输入转义为普通字符串,而Statement可能被恶意输入篡改SQL逻辑。开发中应优先使用PreparedStatement,特别是处理用户输入或高频操作场景。

1. 核心区别总结

2. 逐项详解

(1) SQL构造方式

Statement:直接拼接字符串,容易出错且不安全。

String name = "Alice'; DROP TABLE users;--";
String sql = "SELECT * FROM users WHERE name='" + name + "'";
// 实际SQL:SELECT * FROM users WHERE name='Alice'; DROP TABLE users;--'
// 导致SQL注入!

PreparedStatement:参数化查询,安全隔离数据。

String sql = "SELECT * FROM users WHERE name=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name); // 自动转义危险字符

(2) 预编译机制

Statement:每次执行都需重新编译SQL。

for (int i = 0; i < 1000; i++) {
    String sql = "INSERT INTO logs(msg) VALUES('log" + i + "')";
    stmt.executeUpdate(sql); // 编译1000次!
}

PreparedStatement:一次编译,多次执行。

String sql = "INSERT INTO logs(msg) VALUES(?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
for (int i = 0; i < 1000; i++) {
    pstmt.setString(1, "log" + i);
    pstmt.executeUpdate(); // 仅编译1次!
}

(3) 安全性对比

Statement风险示例

// 用户输入:' OR '1'='1
String input = "' OR '1'='1";
String sql = "SELECT * FROM users WHERE password='" + input + "'";
// 实际SQL:SELECT * FROM users WHERE password='' OR '1'='1' (绕过密码验证)

PreparedStatement防御

String sql = "SELECT * FROM users WHERE password=?";
pstmt.setString(1, input); // 输入会被转义为:\' OR \'1\'=\'1
(4) 性能差异(批量插入10万条数据测试)

3. 加分点

(1) 预编译底层原理
  • 数据库(如MySQL)对预编译语句缓存执行计划。

  • JDBC驱动会发送预编译请求到数据库,后续执行只需传递参数。

  • 可通过prepStmtCacheSize等参数优化缓存策略。

(2) 为什么PreparedStatement能防SQL注入?

参数绑定机制:数据与SQL指令分离,输入内容会被转义。

-- 用户输入:' OR '1'='1
-- 转义后:\' OR \'1\'=\'1
-- 最终SQL:WHERE password='\' OR \'1\'=\'1'
(3) 适用场景选择

用Statement的情况

// 执行DDL语句(无参数)
stmt.execute("CREATE TABLE users(id INT PRIMARY KEY)");

必须用PreparedStatement的情况

// 用户登录验证
String sql = "SELECT * FROM users WHERE username=? AND password=?";
// 高频更新操作
String updateSql = "UPDATE products SET stock=? WHERE id=?";

5.总结:JDBC与数据库操作(快递生活版)

一、核心要点回顾

二、技术选型建议

1.小白起步


✅ 先用连接池+PreparedStatement组合(像用快递柜+电子面单)
✅ 代码模板:

// 连接池配置(快递柜大小设置)
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
config.setUsername("root");
config.setPassword("123456");
config.setMaximumPoolSize(10); // 根据CPU核数设置(4核→8连接)

// 安全查询(防SQL注入)
String sql = "SELECT * FROM users WHERE id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 1001); // 自动消毒用户输入

2.进阶开发

✅ 选择MyBatis(灵活控制SQL)或Spring Data JPA(快速开发)

✅ 警惕ORM的"N+1查询问题"(像代购多次跑腿取货→用JOIN FETCH优化)

3.高并发

✅ 分库分表+连接池(像多个城市的快递分仓)

✅ 分布式事务用Seata(像跨城快递追踪系统)

三、避坑指南

1.绝对不要做


❌ 用Statement拼接用户输入(等于把家门钥匙给陌生人)

// 危险代码示例!(永远别用!)
String input = request.getParameter("password");
String sql = "SELECT * FROM users WHERE password='" + input + "'";
Statement stmt = conn.createStatement();
stmt.executeQuery(sql); // 黑客输入' OR '1'='1 就能入侵!

2.必须要做


✅ 用完立即关闭连接(像快递盒随手回收)
✅ try-with-resources自动回收:

try (Connection conn = dataSource.getConnection();
     PreparedStatement pstmt = conn.prepareStatement(sql)) {
    // 执行操作...
} // 无论成功失败,自动调用close()

许多方法要好好理解,有什么用?怎么使用?要明白

相关文章:

  • BFS最短路径(十七)675. 为高尔夫比赛砍树 困难
  • 图像识别技术与应用(十六)
  • 科技工作者之家建设扬帆起航,为科技人才提供更多优质服务
  • lua C语言api学习1 编译第一个程序
  • 【巨人网络】25届春招、26届实习内推码,面经
  • nginx反向代理应用
  • SMC自修改
  • 二进制安装指定版本的MariaDBv10.11.6
  • 珠算之珠心算观想算盘
  • 基于Python+Vue开发的鲜花商城管理系统源码+运行步骤
  • 深度学习基础:线性代数本质4——矩阵乘法
  • 机器学习之超参数优化(Hyperparameter Optimization)
  • 【leetcode hot 100 23】合并K个有序链表
  • 图像识别技术与应用-YOLO
  • AI日报 - 2025年3月13日
  • Spring Boot 整合 Druid 并开启监控
  • 软件版本号设计
  • IEC61850标准下MMS 缓存报告控制块 ResvTms详细解析
  • 十种处理权重矩阵的方法及数学公式
  • python-leetcode 49.二叉树中的最大路径和
  • 上海市第二十届青少年科技节启动:为期半年,推出百余项活动
  • 试点首发进口消费品检验便利化措施,上海海关与上海商务委发文
  • 马上评|训斥打骂女儿致死,无暴力应是“管教”底线
  • 临港新片区将新设5亿元启航基金:专门投向在临港发展的种子期、初创型企业
  • 董军同德国国防部长举行会谈
  • 俄外交部:俄乌伊斯坦布尔谈判改在当地时间15日下午举行