复习

先来复习一遍要对数据库进行操作的步骤

增删改

  1. 注册驱动
  2. 连接数据库
  3. 准备 PrepareStatement,预处理 SQL 语句
  4. 调用 executeUpdate() 得到 int 类型返回值
  5. 处理数据
  6. 关闭连接

查

  1. 注册驱动
  2. 连接数据库
  3. 准备 PrepareStatement,预处理 SQL 语句
  4. 调用 executeQuery() 得到 ResultSet 类型返回值
  5. 处理数据
  6. 关闭连接

原先代码

如果说看不懂上面我想表达什么,看看这两份代码

增删改

// 注册驱动
String driver = "com.cj.mysql.jdbc.Driver";
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
}

// 建立连接
String url = "jdbc:mysql://localhost:3306/数据库名";
try {
Connection conn = DriverManager.getConnection(url, "root", "123456");

// 创建 PrepareStatement 对象,预处理 SQL 语句
PreparedStatement pstmt = conn.prepareStatement(sql);

// 执行查询
int result = pstmt.executeUpdate();

// 处理结果
if (result >= 1) {
response.getWriter.append("成功!");
} else {
response.getWriter.append("失败");
}

// 关闭连接释放资源
pstmt.close();
conn.close();
} catch (SQLException e) {
}

查

// 注册驱动
String driver = "com.cj.mysql.jdbc.Driver";
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
}

// 建立连接
String url = "jdbc:mysql://localhost:3306/数据库名";
try {
Connection conn = DriverManager.getConnection(url, "root", "123456");

// 创建 PrepareStatement 对象,预处理 SQL 语句
PreparedStatement pstmt = conn.prepareStatement(sql);

// 执行查询
ResultSet rs = pstmt.executeQuery();

// 处理结果
if (rs.next()) {
response.getWriter.append("成功!");
} else {
response.getWriter.append("失败");
}

// 关闭连接释放资源
rs.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
}

MySqlHelper 类提取

经过观察以上两个文件,我们得知其实除了执行查询和处理结果的语句有不同之外,很大一部分的代码都是重复的。所以我们可以将重复的部分提取出来,然后将他们封装成一个类。另外就是,如果没有这么做,那么每次访问数据库的时候,都需要重复写这些冗余的代码

所以我们需要一个类,负责处理数据库的链接和数据库增删改查。

我们把所有重复的代码提取出来,MySqlHelper.java 内容如下:

package com.tootaio.helper;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class MysqlHelper {

// 属性
static String url = "jdbc:mysql://localhost:3306/trading";
static String username = "root";
static String password = "123456";
static Connection conn = null;
static PreparedStatement pstmt = null;
static ResultSet rs = null;

// 3 匿名方法注册驱动
static {
// 注册驱动程序
String driver = "com.mysql.cj.jdbc.Driver";
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

// 4 关闭连接
public static void closeAll() {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}

// 1 方法:查
public static ResultSet executeQuery(String sql) {
ResultSet rs = null;

// 建立连接
try {
conn = DriverManager.getConnection(url, username, password);
// 创建 PreparedStatement 对象
pstmt = conn.prepareStatement(sql);
// 执行查询
rs = pstmt.executeQuery();
// closeAll(); // 暂时不关
} catch (SQLException e) {
e.printStackTrace();
}

return rs;
}

// 2 方法:增删改
public static int executeUpdate(String sql) {
int result = 0;

try {
conn = DriverManager.getConnection(url, "root", "123456");
// 创建 PreparedStatement 对象
pstmt = conn.prepareStatement(sql);
// 执行查询
result = pstmt.executeUpdate();
closeAll();
} catch (SQLException e) {
e.printStackTrace();
}

return result;
}
}

太长了看不懂?这里就来跟你解释。

首先这个类做了两件事情:

  • 增删改 executeUpdate
  • 查 executeQuery
  • 注册驱动
  • 关闭连接 closeAll

然后我们把他们共用的变量提取出来,得到:

  • url: “jdbc:mysql://localhost:3306/trading”
  • username: “root”
  • password: “123456”
  • Connection 对象 conn
  • PreparedStatement 对象 pstmt
  • ResultSet 对象 rs

executeQuery

要让这个类能够执行查询,我们需要创建一个查询函数。参数列表是SQL语句,然后在里面执行查询操作。最后返回的是 ResultSet 对象。

executeUpdate

这个和查询方法的内容是一模一样的,只不过需要调用 pstmt 的 executeUpdate 函数,然后返回值是 int 类型。

closeAll 函数

因为我们连接数据库,所以执行完操作后需要关闭对象释放资源。但是这边我们不关闭 rs 对象。目前不关

因为 rs 对象是要被返回,如果被关闭了,那么数据就没了。我们将会在下一个版本中解决这个问题。

准备驱动

这里我们用了 static 匿名函数。static 匿名函数的调用时机是第一次使用这个 MySqlHelper 类中被调用。

因为 Class.forName() 是一个函数,函数不能在成员变量的域中被调用,必须要在函数里面才能被调用。