JDBC详解
什么是JDBC?
JDBC(Java Database Connectivity)是一种Java API,用于与各种关系型数据库进行交互,它提供了一套标准的接口,使得Java应用程序能够连接到不同的数据库,并执行SQL语句。
JDBC的作用
-
数据库连接:
-
JDBC提供了一种传统的方式连接各种关系型数据库,如MySQL、Oracle、SQL Server等。
-
-
执行SQL语句:
-
可以执行各种SQL语句,包括查询、插入、更新和删除等操作。
-
-
结果集处理:
-
提供了处理查询结果集(ResultSet)的能力,可以方便地遍历和操作结果集中的数据。
-
为什么使用JDBC?
-
标准化:
-
JDBC提供了一套标准化的API,使得应用程序可以独立于具体的数据库类型进行开发。
-
-
可移植性:
-
由于JDBC是标准的JavaAPI,因此应用程序可以在不同的数据库之间轻松迁移
-
-
灵活性:
-
可以根据需要选择不同的JDBC驱动程序,支持多种数据库。
-
使用场景
-
数据库操作:
-
在Java应用程序中执行CRUD(创建、读取、更新、删除)操作。
-
-
数据访问层:
-
构建持久化框架,如DAO(Data Access Object)模式。
-
-
web应用程序
-
在web应用程序中处理数据库事务和数据操作。
-
MySQL中如何连接数据库并执行SQL操作?
-
添加依赖
<!-- 首先,在项目中添加JDBC驱动的依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.31</version> </dependency>
-
连接数据库并执行查询
public class JDBC {
public static void main(String[] args) throws Exception {
// 1、注册驱动 异常抛出
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取数据库连接
String url = "jdbc:mysql://@localhost:3306/mydatabase";
String username = "root";
String password = "password"; // 自己的账号密码
Connection conn = DriverManager.getConnection(
url, username, password);
// 3、创建Statement对象,用于执行SQL语句
Statement st = conn.createStatement();// 操作SQL的对象
String sql = "select id, username, age from t_user";
ResultSet rs = st.executeQuery(sql);//执行SQL查询 sql查询结果会封装在ResultSet对象中
List<User> userList = new ArrayList<>(); //集合对象(用于存储User对象)
// 4、处理SQL执行结果,遍历结果集,并提取每一行的数据
while (rs.next()){
// 取出一行记录中的id, username, age下的数据
int id = rs.getInt("id");
String name = rs.getString("username");
int age = rs.getInt("age");
// 把一行记录中的数据,封装到User对象中
User user = new User(id, name, age);
userList.add(user);// User对象添加到集合中
}
// 5、释放资源
st.close();
conn.close();
rs.close();
// 遍历集合
for (User user : userList) {
System.out.println(user);
}
}
}
上述代码中用到的类和方法解析:
-
Class.forName
-
作用:加载并注册指定类的JDBC驱动
-
-
DriverManager.getConnection
-
方法:
getConnection(String url, String username, String password)
-
作用:建立与数据库的连接
-
-
Connection
-
作用:表示与数据库的连接
-
常用方法:Statement createStatement():创建Statement对象
-
-
Statement:
-
作用:用于执行SQL语句
-
常用方法:
executeQuery(String sql):执行SQL查询语句并返回ResultSet对象
executeUpdate(String sql):执行SQL更新语句(插入、更新、删除)并返回受影响的行数。
close():关闭Statement对象
-
-
ResultSet
-
作用:表示执行查询后返回的结果集。
-
常用的方法:
next():移动到结果集中的下一行
getInt(String columnName):获取指定列的整数值
getString(String columnName):获取指定列的字符串值
-
预编译技术
在JDBC中,预编译技术(PreparedStatement)用于提高SQL的查询效率和安全性。
预编译技术的作用
-
提高性能
-
预编译可以减少SQL语句的解析次数,提高执行效率。
-
数据库服务器可以缓存预编译技术的SQL语句,从而加快执行速度。
-
-
防止SQL注入
-
预编译SQL语句可以自动处理特殊字符,防止SQL注入攻击。
-
-
简化代码:
-
预编译SQL语句可以简化参数绑定的过程,使代码更加简洁。
-
预编译技术的使用步骤
public static void main(String[] args) throws Exception{
// 1、注册驱动 异常抛出
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取数据库连接
String url = "jdbc:mysql://@localhost:3306/mydatabase";
String username = "root";
String password = "password"; // 自己的账号密码
Connection conn = DriverManager.getConnection(
url, username, password);
// 3、创建PreparedStatement对象,进行预编译
// sql:预编译的SQL语句,其中 ? 表示参数占位符
String sql = "insert into t_student(name, age, gender, dob) "
+ "values(?, ?, ?, now())";
PreparedStatement pst = conn.prepareStatement(sql);
// 4、设置参数
// 给第1个问号赋值为"tom" + i拼接的字符串
pst.setString(1, "tom");
// 给第2个问号赋值为22
pst.setInt(2, 22);
// 给第3个问号赋值为"male"字符串
pst.setString(3, "male");
// 执⾏SQL命令(注意,这⾥不带参数)
pst.execute();
ResultSet resultSet = pst.executeQuery();
// 5、遍历结果集
while (resultSet.next()){
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
Date dob = resultSet.getDate("dob");
System.out.println("name: " + name +
",age: " + age +
",gender: " + gender +
",dob: " + dob);
}
// 6、关闭资源
resultSet.close();
pst.close();
conn.close();
}
预编译中用到的方法解析
-
PreparedStatement
-
作用:用于执行预编译的SQL语句
-
常用方法:
setInt(int parameterIndex, int x):设置指定索引处的参数为整数
setString(int parameterIndex, String x):设置指定索引处的参数为字符串
executQuery():执行SQL查询并返回ResultSet对象
executeUpdate():执行SQL更新(插入、更新、删除)并返回受影响的行数
-
小结
预编译技术(PreparedStatement
)是 JDBC 中非常重要的技术,用于提高 SQL 查询的性能和安全性。通过预编译 SQL 语句,可以显著减少数据库服务器的解析开销,并防止 SQL 注入攻击。
批量操作的基本原理
批量操作的核心思想是在一次网络往返中发送多个SQL语句给数据库服务器。这样可以减少网络通信次数,从而提高整体性能。
使用PreparedStatement进行批量操作
在JDBC中,可以使用PreparedStatement的addBatch()和executeBatch()方法来实现批量操作。
-
void addBatch():用于将当前的SQL语句添加到批处理队列中。当你需要执行多个相似的SQL语句时,可以使用这个方法来构建一个批处理队列。
用法:在设置好PreparedStatement的参数后,调用addBatch()方法将当前的SQL语句添加到批处理队列中。
-
int[] executeBatch():用于执行批处理队列中的所有SQL语句。它返回一个整数数组,表示每个SQL语句影响的行数。
用法:在添加完所有需要执行的SQL语句后,调用executeBatch()方法进行批量插入操作。
批量插入操作
class User {
private String name;
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
}
public class JdbcBatchInsertExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "password";
try {
// 1、加载 JDBC 驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、建立数据库连接
Connection connection = DriverManager.getConnection(url, username, password);
// 设置不自动提交
connection.setAutoCommit(false);
// 3、创建 PreparedStatement 对象
String insertSql = "INSERT INTO users (name, email) VALUES (?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(insertSql);
// 4、准备数据
List<User> users = Arrays.asList(
new User("Alice", "alice@example.com"),
new User("Bob", "bob@example.com"),
new User("Charlie", "charlie@example.com")
);
// 5、添加数据到批处理队列
for (User user : users) {
preparedStatement.setString(1, user.getName());
preparedStatement.setString(2, user.getEmail());
preparedStatement.addBatch();
}
// 6、执行批量插入
int[] results = preparedStatement.executeBatch();
// 提交事务
connection.commit();
// 输出结果
for (int result : results) {
System.out.println(result + " row(s) inserted.");
}
// 7、关闭资源
preparedStatement.close();
connection.close();
} catch (Exception e) {
try {
if (connection != null) {
connection.rollback();
}
} catch (Exception ex) {
ex.printStackTrace();
}
e.printStackTrace();
}
}
}