#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

