#java.sql.PreparedStatement

# 描述

java.sql.PreparedStatement接口继承了Statement对象,是实现JDBC预编译SQL语句的对象。

用户可将SQL语句预编译并存储在PreparedStatement对象中,之后可以使用此对象多次有效地执行SQL语句。

详细接口说明请参考JDBC官方网站 (opens new window)。

Note:

YashanDB中,PreparedStatement的SQL语句最多支持32000个参数。

# 方法

YashanDB JDBC驱动对PreparedStatement接口有如下方法:

方法 返回类型
addBatch() void
clearParameters() void
setArray​(int parameterIndex, Array x) void
execute() boolean
executeLargeUpdate() long
executeQuery() ResultSet
executeUpdate() int
getGeneratedKeys() ResultSet
getMetaData() ResultSetMetaData
getParameterMetaData() ParameterMetaData
setBigDecimal​(int parameterIndex, BigDecimal x) void
setBoolean​(int parameterIndex, boolean x) void
setByte​(int parameterIndex, byte x) void
setDate​(int parameterIndex, Date x) void
setDate​(int parameterIndex, Date x, Calendar cal) void
setDouble​(int parameterIndex, double x) void
setFloat​(int parameterIndex, float x) void
setInt​(int parameterIndex, int x) void
setLong​(int parameterIndex, long x) void
setBlob​(int parameterIndex, Blob x) void
setBytes​(int parameterIndex, byte[] x) void
setClob​(int parameterIndex, Clob x) void
setNull​(int parameterIndex, int sqlType) void
setNull(int index, int sqlType, String typeName) void
setObject​(int parameterIndex, Object x) void
setObject​(int parameterIndex, Object x, int targetSqlType) void
setObject​(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) void
setObject​(int parameterIndex, Object x, SQLType targetSqlType) void
setObject​(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) void
setRowId​(int parameterIndex, RowId x) void
setShort​(int parameterIndex, short x) void
setString​(int parameterIndex, String x) void
setNString​(int parameterIndex, String value) void
setTimestamp​(int parameterIndex, Timestamp x) void
setTimestamp​(int parameterIndex, Timestamp x, Calendar cal) void
setTimestamp(int i, java.time.OffsetDateTime offsetDateTime) void
setTime​(int parameterIndex, Time x) void
setTime​(int parameterIndex, Time x, Calendar cal) void
setBinaryStream​(int parameterIndex, InputStream x) void
setBinaryStream​(int parameterIndex, InputStream x, int length) void
setBinaryStream​(int parameterIndex, InputStream x, long length) void
setBlob​(int parameterIndex, InputStream inputStream) void
setBlob​(int parameterIndex, InputStream inputStream, long length) void
setClob​(int parameterIndex, Reader reader) void
setClob​(int parameterIndex, Reader reader, long length) void
setNClob​(int parameterIndex, Reader reader) void
setNClob​(int parameterIndex, Reader reader, long length) void
setNClob​(int parameterIndex, NClob value) void
setAsciiStream​(int parameterIndex, InputStream x) void
setAsciiStream​(int parameterIndex, InputStream x, int length) void
setAsciiStream​(int parameterIndex, InputStream x, long length) void
setCharacterStream​(int parameterIndex, Reader reader) void
setCharacterStream​(int parameterIndex, Reader reader, int length) void
setCharacterStream​(int parameterIndex, Reader reader, long length) void
setSQLXML​(int parameterIndex, SQLXML xmlObject) void

YashanDB JDBC驱动PreparedStatement扩展接口功能:

方法 说明
void setIsBatchError(boolean batchError); 设置是否批量报错,若设置为true,则多条数据为一批进行批量执行时,如果某一条或者某几条有数据错误时不会立即报错停止执行,而是把后面的全部执行完,最后通过getBatchError来获取报错行的报错信息。
boolean getIsBatchError(); 获取是否批量报错。
String getBatchError(int batchIndex); 在setIsBatchError设置为true的情况下在批量执行结束后获取报错行的报错信息。

# 示例

package quickstart;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class PreparedStatementExample {

    public static Connection getConnection()
            throws SQLException, ClassNotFoundException {
        String url = "jdbc:yasdb://192.168.1.2:1688/yasdb";
        Properties info = new Properties();
        info.setProperty("user", "username");
        info.setProperty("password", "passwd");
        Class.forName("com.yashandb.jdbc.Driver");
        return DriverManager.getConnection(url, info);
    }

    // 获取参数元数据
    public void parameterMetadata(Connection conn) throws SQLException {
        String sql = "SELECT id, name FROM users WHERE name LIKE ? AND age >= ?";
        // 创建PreparedStatement对象,并使用参数占位符避免拼接SQL。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            // 获取PreparedStatement中参数的信息。
            ParameterMetaData metadata = ps.getParameterMetaData();
            System.out.println("Parameter count: " + metadata.getParameterCount());
        }
    }

    // 分页查询
    public void pagedQuery(Connection conn, int page, int size) throws SQLException {
        String sql = "SELECT id, name FROM products ORDER BY id LIMIT ? OFFSET ?";
        // 创建PreparedStatement对象,预编译分页查询语句。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            // 绑定分页大小和偏移量参数。
            ps.setInt(1, size);
            ps.setInt(2, (page - 1) * size);
            // 执行PreparedStatement查询并读取结果集。
            try (ResultSet rs = ps.executeQuery()) {
                int rows = 0;
                while (rs.next()) {
                    rows++;
                }
                System.out.println("Paged query rows: " + rows);
            }
        }
    }

    // 条件查询
    public void conditionalQuery(Connection conn, String name, Integer minAge)
            throws SQLException {
        String sql = "SELECT * FROM users WHERE 1=1";
        if (name != null) sql += " AND name LIKE ?";
        if (minAge != null) sql += " AND age >= ?";

        // 创建PreparedStatement对象,按条件动态绑定参数。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            int index = 1;
            if (name != null) {
                // 绑定名称模糊匹配参数。
                ps.setString(index++, "%" + name + "%");
            }
            if (minAge != null) {
                // 绑定最小年龄参数。
                ps.setInt(index++, minAge);
            }

            int rows = 0;
            // 执行PreparedStatement查询并统计结果行数。
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    rows++;
                }
            }
            System.out.println("Conditional query rows: " + rows);
        }
    }

    // 单行插入
    public void insertProduct(Connection conn, int id, String name)
            throws SQLException {
        String sql = "INSERT INTO products (id, name) VALUES (?, ?)";
        // 创建PreparedStatement对象,预编译插入语句。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            // 绑定插入数据。
            ps.setInt(1, id);
            ps.setString(2, name);
            // 执行PreparedStatement更新并获取受影响行数。
            int rows = ps.executeUpdate();
            System.out.println("Inserted product rows: " + rows);
        }
    }

    // 批量插入
    public void batchInsertUsers(Connection conn) throws SQLException {
        String sql = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)";
        // 创建PreparedStatement对象,复用预编译的批量插入语句。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            // 绑定第1条数据并加入批处理。
            ps.setInt(1, 3);
            ps.setString(2, "Carol");
            ps.setInt(3, 25);
            ps.addBatch();

            // 清理当前参数并绑定第2条数据。
            ps.clearParameters();
            ps.setInt(1, 4);
            ps.setString(2, "David");
            ps.setInt(3, 28);
            ps.addBatch();

            // 执行PreparedStatement批处理。
            int[] results = ps.executeBatch();
            System.out.println("Batch inserted user rows: " + results.length);
        }
    }

    // 复用参数执行
    public void reuseParameters(Connection conn) throws SQLException {
        String sql = "INSERT INTO products (id, name) VALUES (?, ?)";
        // 创建PreparedStatement对象,后续多次复用同一预编译语句。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            // 绑定第1条数据并执行PreparedStatement。
            ps.setInt(1, 4);
            ps.setString(2, "Monitor");
            boolean firstResult = ps.execute();

            // 清理已绑定参数后,重新绑定第2条数据。
            ps.clearParameters();
            ps.setInt(1, 5);
            ps.setString(2, "Printer");
            boolean secondResult = ps.execute();

            System.out.println("Execute returned result set: "
                    + firstResult + ", " + secondResult);
        }
    }

    // 大数据量更新
    public void largeUpdate(Connection conn) throws SQLException {
        String sql = "UPDATE accounts SET balance = balance + ? WHERE id = ?";
        // 创建PreparedStatement对象,预编译更新语句。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            // 绑定更新金额和账户编号。
            ps.setBigDecimal(1, new BigDecimal("10"));
            ps.setInt(2, 1);
            // 执行PreparedStatement并获取long类型的更新行数。
            long rows = ps.executeLargeUpdate();
            System.out.println("Large update rows: " + rows);
        }
    }

    // 事务更新
    public void transactionUpdate(Connection conn) throws SQLException {
        conn.setAutoCommit(false);
        String sql = "UPDATE accounts SET balance = balance - ? WHERE id = ?";

        // 创建PreparedStatement对象,在事务中复用预编译更新语句。
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            // 从账户1转出资金
            // 绑定转出金额和账户编号。
            ps.setBigDecimal(1, new BigDecimal("100"));
            ps.setInt(2, 1);
            // 执行第1次PreparedStatement更新。
            int debitRows = ps.executeUpdate();

            // 向账户2转入资金
            // 重新绑定转入金额和账户编号。
            ps.setBigDecimal(1, new BigDecimal("100"));
            ps.setInt(2, 2);
            // 执行第2次PreparedStatement更新。
            int creditRows = ps.executeUpdate();

            // 提交PreparedStatement执行产生的事务。
            conn.commit();
            System.out.println("Transaction committed, rows updated: "
                    + (debitRows + creditRows));
        } catch (SQLException e) {
            conn.rollback();
            throw e;
        } finally {
            conn.setAutoCommit(true);
        }
    }

    public static void main(String[] args) {
        try (Connection conn = getConnection()) {
            try (Statement stmt = conn.createStatement()) {
                try {
                    stmt.execute("DROP TABLE products");
                } catch (SQLException ignored) {
                }
                try {
                    stmt.execute("DROP TABLE users");
                } catch (SQLException ignored) {
                }
                try {
                    stmt.execute("DROP TABLE accounts");
                } catch (SQLException ignored) {
                }

                stmt.execute("CREATE TABLE products ("
                        + "id INT PRIMARY KEY, name VARCHAR(20))");
                stmt.execute("INSERT INTO products VALUES (1, 'Keyboard')");
                stmt.execute("INSERT INTO products VALUES (2, 'Mouse')");
                stmt.execute("CREATE TABLE users ("
                        + "id INT PRIMARY KEY, name VARCHAR(20), age INT)");
                stmt.execute("INSERT INTO users VALUES (1, 'Alice', 30)");
                stmt.execute("INSERT INTO users VALUES (2, 'Bob', 17)");
                stmt.execute("CREATE TABLE accounts ("
                        + "id INT PRIMARY KEY, balance DECIMAL(10, 2))");
                stmt.execute("INSERT INTO accounts VALUES (1, 1000)");
                stmt.execute("INSERT INTO accounts VALUES (2, 500)");
            }

            PreparedStatementExample example = new PreparedStatementExample();
            example.parameterMetadata(conn);
            example.pagedQuery(conn, 1, 10);
            example.conditionalQuery(conn, "Alice", 18);
            example.insertProduct(conn, 3, "Tablet");
            example.batchInsertUsers(conn);
            example.reuseParameters(conn);
            example.largeUpdate(conn);
            example.transactionUpdate(conn);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }
}

正常情况下,程序输出如下:

Parameter count: 2
Paged query rows: 2
Conditional query rows: 1
Inserted product rows: 1
Batch inserted user rows: 2
Execute returned result set: false, false
Large update rows: 1
Transaction committed, rows updated: 2
pdf-btn 下载文档 copy-btn 复制链接
edit-icon
反馈
coperate-icon
coperate
合作
communication-icon
communicate
交流