首页 > 编程笔记 > Java笔记 阅读:4

Java PreparedStatement接口的用法(附带实例)

PreparedStatement 是可以对 SQL 语句进行预编译处理的一个接口,该接口可用于执行动态的 SQL 语句。

所谓动态 SQL 语句,指的是在 SQL 语句中可以提供参数,对相同的 SQL 语句替换参数,进而实现多次使用。因此,当一个 SQL 语句需要执行多次时,使用预编译语句可以减少执行时间。

由于 PreparedStatement 是 Statement 的子接口,所以 PreparedStatement 对象可以执行动态 SQL 语句,也可以执行静态 SQL 语句。

PreparedStatement 接口的常用方法如下表所示:

表 1 PreparedStatement 接口的常用方法
方法 方法描述
int executeUpdate() throws SQLException 执行设置的预处理 SQL 语句
ResultSet executeQuery() throws SQLException 执行数据库查询操作,返回 ResultSet
void setInt(int parameterIndex, int x) throws SQLException 指定要设置的索引编号,并设置整数内容
void setString (int parameterIndex, String x) 指定要设置的索引编号,并设置字符串内容

接下来,通过案例来演示使用 PreparedStatement 接口插入数据(实例 1):
import com.aaa.util.BaseDAO;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Demo {
    public static void main(String[] args) {
        Connection connection = BaseDAO.getConnection();
        PreparedStatement pstmt = null;
        // 定义SQL语句
        String sql = "insert into students(name,gender,age) values(?,?,?)";
        try {
            pstmt = connection.prepareStatement(sql); // 对SQL进行预编译
            // 对占位符按照位置进行数据填充
            pstmt.setString(1, "李四");
            pstmt.setString(2, "男");
            pstmt.setInt(3, 20);
            int i = pstmt.executeUpdate(); // 执行SQL并返回受影响的行数
            System.out.println("受影响的行数为:" + i);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDAO.closeAll(connection, pstmt);
        }
    }
}

程序中很多地方都需要获取数据库的连接并关闭连接,所以将这部分代码提到一个公共的 BaseDAO 类中,并将这个类放到 com.aaa.util 中,代码如下:
package com.aaa.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class BaseDAO {
    // 定义MySQL的数据库驱动程序
    public static final String DRIVER = "com.mysql.jdbc.Driver";
    // 数据库连接字符串
    public static final String URL = "jdbc:mysql://school?useUnicode=true&characterEncoding=utf-8";
    public static final String USER = "root"; // 数据库服务器账号
    public static final String PWSD = "root"; // 数据库服务器密码
    // 数据库连接方法
    public static Connection getConnection() {
        Connection con = null;
        try {
            Class.forName(DRIVER); // 加载驱动类
            con = DriverManager.getConnection(URL, USER, PWSD); // 获取连接
        } catch (ClassNotFoundException e) {
            System.out.println("加载失败"); // 如果有异常会执行
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("连接数据库错误");
            e.printStackTrace();
        }
        return con;
    }

    public static void closeAll(Connection con) { // 关闭数据库对象方法
        try {
            if (con != null) {
                con.close();
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}
程序的运行结果如下:

受影响的行数为:1

程序中,使用 PreparedStatement 对象执行添加操作。与 Statement 接口的用法不同的是,该接口先对 SQL 语句进行预编译,然后将需要设置值的地方使用占位符“?”来占位,并在调用 executeUpdate() 方法之前对占位符进行赋值,赋值的时候调用的是 setXXX() 方法(XXX 代表的是要赋给的参数的具体数据类型)。

Statement 接口在执行时使用的是静态 SQL 语句,而 PreparedStatement 接口使用占位符的方式来执行 SQL 语句。这种方式能够有效防止 SQL 注入攻击,所以推荐使用 PreparedStatement 接口来执行 SQL 语句。

在数据库处理中,增删改是十分常用的操作,所以要进行封装,以实现代码的复用。另外,执行 SQL 语句时,一般也需要设置 SQL 语句中的参数数据,这个方法也可以封装成通用的方法。

下面将增删改方法和设置参数的方法封装到 BaseDAO 类中,代码如下:
package com.aaa.util;
import java.sql.*;

public class BaseDAO {
    // 此处省略获取连接和关闭连接的方法
    // 通用设置参数的方法
    public static void setParams(PreparedStatement pst, Object[] params) {
        if (params == null) { // 如果没有数据,则不作设置
            return;
        }
        try {
            for (int i = 0; i < params.length; i++) { // 循环设置参数
                pst.setObject(i + 1, params[i]);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // 通用增删改方法
    public static int executeUpdate(String sql, Object[] params) {
        Connection con = null;
        PreparedStatement pst = null;
        int res = 0;
        try {
            con = getConnection(); // 创建连接
            pst = con.prepareStatement(sql);
            setParams(pst, params); // 设置参数值
            res = pst.executeUpdate(); // 执行增删改操作
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            closeAll(con, pst, null);
        }
        return res;
    }
}

接下来,使用封装后的 BaseDAO 类来实现例 1 的功能:
import com.aaa.util.BaseDAO;

public class Demo {
    public static void main(String[] args) {
        String sql = "insert into students(name,gender,age) values(?,?,?)";
        Object[] params = {"李四", "男", 20};
        int i = BaseDAO.executeUpdate(sql, params);
        System.out.println("受影响的行数为:" + i);
    }
}
程序的运行结果如下:

受影响的行数为:1

相关文章