复习

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

增删改

  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() 是一个函数,函数不能在成员变量的域中被调用,必须要在函数里面才能被调用。