JDBC
JDBC
一、 JDBC简介
JDBC就是由sun公司定义的一套操作所有关系型数据库的规则(接口), 而数据库厂商需要实现这套接口, 厂商的实现类在引入的数据库驱动jar包中。
-
-
是一种执行SQL的API, 可以为多种关系型数据库提供统一的访问。
-
数据库驱动程序
- 是直接操作数据库的一个程序;
- 不同数据库的驱动名字有差异;
- 在程序中需要依赖数据库驱动来完成对数据库的操作。
二、 JDBC实现增删改查
使用JDBC要先引入数据库驱动包
1. 查询
1.1 流程
① 加载(注册)驱动
Class.forName(数据库启动实现类)
作用:触发类加载,执行静态代码块
Driver类中的静态代码块如下:
就是将Driver对象交给DriverManager管理了。
DriverManager是驱动管理类,可以通过驱动管理类获取到数据库的连接
注意: JDBC4.0之后, 在每个驱动jar包中META-INF/services目录下提供了一个名为java.sql.Driver的文件。
② 获取连接
JDBC提供了Connection接口,代表一个数据库连接接口。
MySQL通过DriverManager类中的静态方法 getConnection()获取连接。
Connection getConnection(String url, String user, String password)
String url="jdbc:mysql://localhost:3306/sygg?
useSSL=false&useUnicode=true
&characterEncoding=utf-8&&serverTimezone=Asia/Shanghai";
第一部分是协议 jdbc,这是固定的
第二部分是子协议,就是数据库名称,连接mysql数据库,第二部分当然是mysql了
③ 获取SQL执行器
通过Connection的 createStatement()方法获取sql语句执行对象
Statement createStatement()
④ 发送SQL,数据库执行SQL,获取返回结果
Statement对象用于发送SQL语句给MySQL服务器,执行SQL 语句并返回它所生成结果。
Statement类常用方法 | 说明 |
---|---|
int executeUpdate(String sql) | 执行insert、delete、update语句,返回int类型,代表受影响的函数 |
ResultSet executeQuery(String sql) |
⑤ 处理结果集
查询后的结果会存放到ResultSet结果集中。
ResultSet接口方法 | 说明 |
---|---|
boolean next() |
1.游标向下一行 2.返回boolean类型,如果有下一条记录,返回true,否则返回false |
xxx getXxx(String or int) |
1.通过列名获取数据
|
ResultSet特点
原理
⑥ 释放资源
最后释放相关的资源即可:
-
-
ResultSet结果集: 当它的 Statement 关闭、重新执行或用于从多结果序列中获取下一个结果时,该ResultSet将被自动关闭
-
//6. 释放资源 statement.close(); connection.close();
2. 增、删、改
和查询流程类似(比查询少了个处理结果集的步骤)
需要注意的是增删改调用了statement.executeUpdate(sql),而查询时调用的是executeQuery(sql)方法
另外,增删改执行方法后返回的是int类型,即返回影响的行数,而查询返回的查询到的记录(ResultSet结果集)。
三、ORM
ORM(Object Relational Mapping,简称ORM,或O/R mapping)对象关系映射。
是一种为了解决面向对象语言与关系数据库存在的互不匹配的现象。
即数据库中一张表对应java的一个类。
四、 PreparedStatement预处理对象
通过PreparedStatement可以解决SQL注入的问题。
SQL注入
SQL注入就是 手动输入的内容作为SQL语句的一部分,但改变了SQL语句的本意
1. PreparedStatement接口
2. 特点
3. 获取PreparedStatement对象
通过Connection创建PreparedStatement对象。
Connection接口中的方法 | 说明 |
---|---|
PreparedStatement prepareStatement(String sql) |
4. 常用方法
常用方法 | 说明 |
---|---|
int executeUpdate() | 执行insert、delete、update语句 |
ResultSet executeQuery() |
5. 如何使用
① 编写SQL语句,未知内容用占位符 ? 代替
② 调用connection.prepareStatement(sql)方法获取PreparedStatement对象
③ 设置实际参数,即给占位符 ? 赋值:setXX(占位符的位置,真实的值)
注意:占位符的位置下标从1开始。
④ 执行SQL
6. 执行原理
Statement会在执行SQL时才进行解析、预处理,效率慢且存在SQL注入问题
而PreparedStatement在执行SQL前就会进行解析、预处理,语义已经确定不会再被改变,给占位符赋的值仅仅被当做一个值而不是SQL语句的一部分。
另外,statement执行多条SQL就会多次进行解析、预处理,而PreparedStatement只进行一次解析、预处理。
7. 批处理
PreparedStatement中的addBatch()方法:添加到批量操作
可以用于批量的写操作(增删改,主要用于添加数据)。
-
批处理是指将关联的SQL语句组合成一个批处理,并将他们当成一次调用提交给数据库, 一次发送多个SQL语句到数据库,可以减少通信的资源消耗,从而提高了性能
-
executeBatch() 方法用于启动执行所有组合在一起的语句。
-
对于多次操作,批处理又进一步提升了效率。
8. 获取自增主键值
调用connection的prepareStatement()方法创建预编译对象prepareStatement时增加一个 Statement.RETURN_GENERATED_KEYS 参数
执行sql后,调用prepareStatement对象的 getGeneratedKeys() 返回一个ResultSet对象,遍历ResultSet就能拿到自增的主键值。
五、 JDBC事务控制
1. 事务概述
1. 读未提交: 脏读 不可重复读 幻读
2. 读已提交: 不可重复读 幻读
3. 可重复读: 幻读
4. 串行化: 完全解决,整张表加锁, 同时只能有一个客户端操作。
事务是一个整体, 由一条或者多条SQL语句组成, 这些SQL语句要么都执行成功, 要么就失败, 只要有一条SQL出现异常, 整个操作就会回滚。
回滚: 就是事务运行的过程中发生了某种故障, 或者SQL出现了异常, 事务不能继续执行, 系统将事务中对数据库的所有已完成的操作全部取消, 回滚到事务开始时的状态。
宕机等情况自动回滚, 代码的bug手动回滚。
事务控制的使用方式:
1. 使用MySQL的命令来操作事务控制
2. 事务相关API
通过connection中的方法实现事务控制
方法 | 说明 |
---|---|
void setAutoCommit(boolean autoCommit) | 参数设置为true,表示自动提交; 设置为false,表示手动提交 |
void commit() | 提交事务 |
void rollback() |
rollback回滚事务在catch代码块中执行,即出现错误时及时回滚事务。
最后在finally代码块中释放资源。
六、 连接池
数据库连接池的基本原理是连接池对象中维护一定数量的数据库连接,并对外暴露数据库连接获取和返回方法
1. 连接池工具类
-
-
DBCP数据库连接池,速度相比C3P0快,但不稳定。
-
1.1 C3P0使用
//创建一个数据源对象 ComboPooledDataSource cpds = new ComboPooledDataSource(); String url = "jdbc:mysql://localhost:端口号/数据库名?useSSL=false&useUnicode=true" + "&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; String driver = "com.mysql.cj.jdbc.Driver"; String username = "数据库用户名"; String password = "数据库密码"; cpds.setDriverClass(driver); cpds.setJdbcUrl(url); cpds.setUser(username); cpds.setPassword(password); //设置初始化连接数 cpds.setInitialPoolSize(10); //最大连接数 cpds.setMaxPoolSize(50); //测试连接池的效率, 测试对 mysql 5000 次操作 long start = System.currentTimeMillis(); for (int i = 0; i < 5000; i++) { Connection connection = cpds.getConnection(); connection.close(); } long end = System.currentTimeMillis(); System.out.println("c3p0 5000 连接 mysql 耗时=" + (end - start));
1.2 Druid使用
DruidDataSource dbs = new DruidDataSource(); String url = "jdbc:mysql://localhost:端口号/数据库名?useSSL=false&useUnicode=true" + "&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; String driver = "com.mysql.cj.jdbc.Driver"; String username = "数据库用户名"; String password = "数据库密码"; dbs.setDriverClassName(driver); dbs.setUrl(url); dbs.setUsername(username); dbs.setPassword(password); //测试连接池的效率, 测试对 mysql 5000 次操作 long start = System.currentTimeMillis(); for (int i = 0; i < 500000; i++) { Connection connection = dbs.getConnection(); connection.close(); } long end = System.currentTimeMillis(); System.out.println("druid 5000 连接 mysql 耗时=" + (end - start));
2. Druid封装工具类

public class DruidUtils { private static DruidDataSource dbs; static { String url = "jdbc:mysql://localhost:3306/zqwl?useSSL=false&useUnicode=true" + "&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; String driver = "com.mysql.cj.jdbc.Driver"; String username = "root"; String password = "root"; try { dbs = new DruidDataSource(); dbs.setDriverClassName(driver); dbs.setUrl(url); dbs.setUsername(username); dbs.setPassword(password); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dbs.getConnection(); } public static void close(Statement statement, Connection connection) { try { if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { throw new RuntimeException(e); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异