JDBC编程
一、JDBC基础概念
1. JDBC是什么?
JDBC(Java Database Connectivity)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口
2. JDBC驱动类型
Type 1: JDBC-ODBC Bridge
Type 2: Native API Partly Java Driver
Type 3: Net Protocol All Java Driver
Type 4: Thin Driver (Pure Java)
3. 常用数据库URL格式
MySQL:
jdbc:mysql://hostname:port/database
Oracle:
jdbc:oracle:thin:@hostname:port:SID
SQL Server:
jdbc:microsoft:sqlserver://hostname:port;databaseName=database
二、JDBC核心API
1. DriverManager
管理JDBC驱动的服务类
常用方法:
Connection getConnection(String url, String user, String password)
2. Connection
数据库连接接口
常用方法:
Statement createStatement()
PreparedStatement prepareStatement(String sql)
void setAutoCommit(boolean autoCommit)
void commit()
void rollback()
3. Statement
执行SQL语句的接口
常用方法:
ResultSet executeQuery(String sql)
(用于SELECT)int executeUpdate(String sql)
(用于INSERT/UPDATE/DELETE)
4. PreparedStatement
继承自Statement,防止SQL注入
常用方法:
void setXxx(int parameterIndex, Xxx value)
(设置参数)
5. ResultSet
结果集接口,用于保存查询结果
常用方法:
boolean next()
(移动光标到下一行)getXxx(int columnIndex)
或getXxx(String columnName)
(获取列值)
三、JDBC开发步骤(经典6步法)
加载JDBC驱动:
Class.forName("com.mysql.cj.jdbc.Driver")
建立数据库连接:
DriverManager.getConnection(url, user, password)
创建Statement对象:
connection.createStatement()
执行SQL语句:
statement.executeQuery(sql)
处理结果集(仅限查询):
while (resultSet.next()) {int id = resultSet.getInt("id");String name = resultSet.getString("name"); }
关闭资源(按顺序):
resultSet.close(); statement.close(); connection.close();
四、PreparedStatement详解
1. 使用步骤
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, "张三");
ps.setString(2, "zhangsan@example.com");
int rowsAffected = ps.executeUpdate();
2. 占位符使用
使用
?
作为占位符,通过setXxx()
方法设置参数参数索引从1开始计数
3. 优势
防止SQL注入
提高性能(可重用)
提高代码可读性和可维护性
4.基本CRUD
create table t_user
(id bigint not null auto_increment comment '主键',name varchar(255) not null comment '用户名',password varchar(255) not null comment '密码',realname varchar(255) comment '真实姓名',gender char(1) comment '性别',tel char(11) comment '联系电话',primary key (id)
);
alter table t_user comment '这是一张存储用户信息的表';
INSERT INTO t_user (name, password, realname, gender, tel) VALUES
('user_zhangwuji', '123456', '张无忌', '男', '13800001111'),
('user_zhaomin', '123456', '赵敏', '女', '13800002222'),
('user_xiaolongnu', '123456', '小龙女', '女', '13800003333'),
('user_guojing', '123456', '郭靖', '男', '13800004444'),
('user_huangrong', '123456', '黄蓉', '女', '13800005555'),
('user_duanyu', '123456', '段誉', '男', '13800006666'),
('user_linghuchong', '123456', '令狐冲', '男', '13800007777'),
('user_renyingying', '123456', '任盈盈', '女', '13800008888'),
('user_ouyangfeng', '123456', '欧阳锋', '男', '13800009999'),
('user_hongqigong', '123456', '洪七公', '男', '13800000000');
package com.mysql.test01;
import java.sql.*;
public class JDBCTest {public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;String sql = "insert into t_user(name,password,realname,gender,tel) values(?,?,?,?,?)";String sql1="update t_user set password=? where name=?";String sql2="select * from t_user limit ?,?";String sql4="delete from t_user where name=? ";int page=4;int pageNumber=4;
String sql3="select * from t_user where name like ?";try {conn = DbUtils.getConnection();ps = conn.prepareStatement(sql3);ps.setString(1,"%g");rs = ps.executeQuery();while(rs.next()){int id = rs.getInt("id");String name = rs.getString("name");String password = rs.getString("password");String realname = rs.getString("realname");String gender = rs.getString("gender");String tel = rs.getString("tel");System.out.println(id + "\t" + name + "\t" + password + "\t" + realname + "\t" + gender + "\t" + tel);}} catch (SQLException e) {e.printStackTrace();} finally {DbUtils.close(rs, ps, conn);}}
}
五、事务管理
1. 事务特性(ACID)
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
2. JDBC事务控制
connection.setAutoCommit(false); // 开启事务
try {// 执行多个数据库操作connection.commit(); // 提交事务
} catch (SQLException e) {connection.rollback(); // 回滚事务
}
示例:
create table account(
id int primary key AUTO_INCREMENT comment 'ID',
name varchar(10) comment '姓名',
money double(10,2) comment '余额'
) comment '账户表';
insert into account(name, money) VALUES ('张三',2000), ('李四',2000);
package com.mysql.test01.test02;
import com.mysql.test01.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Account {public static void main(String[] args) {Connection conn = null;PreparedStatement ps1 = null;PreparedStatement ps2 = null;ResultSet rs = null;try {conn = DbUtils.getConnection();conn.setAutoCommit(false);String sql1 = "update account set money=money-? where name=?";String sql2 = "update account set money=money+? where name=?";ps1 = conn.prepareStatement(sql1);ps1.setDouble(1, 1000);ps1.setString(2, "张三");ps1.executeUpdate();ps2 = conn.prepareStatement(sql2);ps2.setDouble(1,1000);ps2.setString(2,"李四");ps2.executeUpdate();conn.commit();} catch (SQLException e) {try {conn.rollback();} catch (SQLException ex) {e.printStackTrace();}e.printStackTrace();} finally {DbUtils.close(rs, ps2, conn);DbUtils.close(null, ps1, null);}}
}
六、连接池技术
1. 为什么需要连接池?
避免频繁创建和关闭连接
提高系统性能
控制连接数量
2. 常见连接池实现
DBCP
C3P0
Druid
HikariCP
3. 使用示例(以Druid为例)
// 配置Druid连接池
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("password");// 获取连接
Connection connection = dataSource.getConnection();
七、数据库元数据
1. DatabaseMetaData
获取数据库信息(数据库版本、支持的SQL语法等)
使用方法:
DatabaseMetaData metaData = connection.getMetaData(); ResultSet rs = metaData.getTables(null, null, "%", null);
2. ResultSetMetaData
获取结果集结构信息(列名、列类型等)
使用方法:
ResultSetMetaData metaData = resultSet.getMetaData(); int columnCount = metaData.getColumnCount(); for (int i = 1; i <= columnCount; i++) {String columnName = metaData.getColumnName(i);String columnType = metaData.getColumnTypeName(i); }
八、最佳实践
1. 使用try-with-resources(Java 7+)
try (Connection conn = DriverManager.getConnection(url, user, password);PreparedStatement ps = conn.prepareStatement(sql)) {// 使用资源
} catch (SQLException e) {// 异常处理
}
2. 使用DAO模式
分离业务逻辑和数据访问逻辑
提高代码可维护性和可测试性
3. 使用工具类封装
封装获取连接、关闭资源等通用操作
提高代码复用率
4. 异常处理策略
分层处理异常
记录日志
合理转换异常