Statement
用于执行静态SQL并返回结果对象。
默认情况下,每个Statement对象只能有一个ResultSet对象同时打开。如果打开ResultSet则会隐式关闭当前ResultSet对象。
- 属性
// ResultSet能返回的最大行数,超过则丢弃
// 0表示无限制
int getMaxRows();
void setMaxRows(int max);
// ResultSet行被处理的方向
// 可为
// ResultSet.FETCH_FORWARD(默认,1000)
// ResultSet.FETCH_REVERSE(1001)
// ResultSet.FETCH_UNKNOWN(1002)
int getFetchDirection();
void setFetchDirection(int direction);
// 一次查询返回的行数
// 0表示无限制,默认为0
int getFetchSize();
void setFetchSize(int rows);
// ResultSet类型
// 可为
// ResultSet.TYPE_FORWARD_ONLY(1003)
// ResultSet.TYPE_SCROLL_INSENSITIVE(1004)
// ResultSet.TYPE_SCROLL_SENSITIVE(1005)
int getResultSetType();
// ResultSet并发类型
// 可为
// ResultSet.CONCUR_READ_ONLY(1007)
// ResultSet.CONCUR_UPDATABLE(1008)
int getResultSetConcurrency();
// ResultSet保持类型
// 可为
// ResultSet.HOLD_CURSORS_OVER_COMMIT(1)
// ResultSet.CLOSE_CURSORS_AT_COMMIT(2)
int getResultSetHoldability();
// 超时秒数
// 0表示无限制,默认为0
int getQueryTimeout();
void setQueryTimeout(int seconds);
// 当所有ResultSet关闭时是否自动关闭Statement
boolean isCloseOnCompletion();
void closeOnCompletion();
- 查询
ResultSet executeQuery(String sql);
例:
// executeQuery
ResultSet resultSet = statement.executeQuery("select *, id as userId from user");
while (resultSet.next()) {
// 列标
long userId = resultSet.getLong("userId");
String userName = resultSet.getString("userName");
System.out.println(userId + " " + userName);
}
resultSet.close();
- 更新
// 返回影响行数
int executeUpdate(String sql);
- 多结果
// 执行给定SQL,可能返回多个结果(一般是调用存储过程)
// 先使用getResultSet()或getUpdateCount()获取第一个结果(已移动到第一个结果)
// 然后再使用getMoreResults()判断下一个结果类型
// 返回:
// true:第一个结果是ResultSet
// false:第一个结果是更新数,或没有更多结果
boolean execute(String sql);
// 移动到下一个结果
// 返回:
// true:下个结果是ResultSet
// false:下个结果是更新数,或没有更多结果
boolean getMoreResults();
// 移动到下一个结果,并处理当前ResultSet
// current:
// Statement.CLOSE_CURRENT_RESULT(1)
// Statement.KEEP_CURRENT_RESULT(2)
// Statement.CLOSE_ALL_RESULTS(3)
boolean getMoreResults(int current);
// 返回更新数
// -1:当前结果是ResultSet,或没有更多结果
int getUpdateCount();
// 返回ResultSet
// null:当前结果是更新数,或没有更多结果
ResultSet getResultSet();
例:
// 存储过程
// mysql> delimiter $$ // 临时将结束符由;改为$$
// mysql> create procedure getTwoUsers()
// -> begin
// -> select * from user where id = 1;
// -> select * from user where id = 2;
// -> update user set status = 3 where id = 3;
// -> end$$
// mysql> delimiter ;
// mysql> call getTwoUsers();
// 多结果
String sql = "call getTwoUsers()";
// 已经移动到下一个结果
boolean isResultSet = statement.execute(sql);
int resultIndex = 0;
while (true) {
if (isResultSet) {
System.out.println("结果" + (++resultIndex) + ":");
ResultSet resultSet = statement.getResultSet();
while (resultSet.next()) {
long id = resultSet.getLong("id");
String userName = resultSet.getString("userName");
System.out.println(id + " " + userName);
}
resultSet.close();
} else {
int updateCount = statement.getUpdateCount();
if (updateCount == -1) {
// 结果遍历结束:getMoreResults()==false && getUpdateCount()==-1
break;
} else {
System.out.println("结果" + (++resultIndex) + ":");
System.out.println("更新数:" + updateCount);
}
}
System.out.println();
isResultSet = statement.getMoreResults();
}
- 批量更新
void addBatch(String sql);
void clearBatch();
// 批量执行SQL,返回更新数数组
// 更新数 >=0,表示影响行数
// 更新数 = Statement.SUCCESS_NO_INFO(-2),表示影响行数未知
// 如果其中一个SQL出错,抛出BatchUpdateException
int[] executeBatch();
- BatchUpdateException
// 批量更新时各SQL的更新数结果
// 更新数 = Statement.EXECUTE_FAILED(-3),表示执行失败
int[] getUpdateCounts();
例:
String[] sqlList = new String[]{
"update user set status = 1 where id = 1",
"update user set status = 2 where id = a",
"update user set status = 3 where id = 3"
};
Consumer updateCountsConsumer = new Consumer() {
@Override
public void accept(int[] updateCounts) {
for (int i = 0; i < sqlList.length; i++) {
String sql = sqlList[i];
int updateCount = updateCounts[i];
if (updateCount == Statement.SUCCESS_NO_INFO) {
System.out.println(sql + ":未知");
} else if (updateCount == Statement.EXECUTE_FAILED) {
System.out.println(sql + ":失败");
} else {
System.out.println(sql + ":" + updateCount);
}
}
}
};
try {
for (String sql : sqlList) {
statement.addBatch(sql);
}
int[] updateCounts = statement.executeBatch();
updateCountsConsumer.accept(updateCounts);
} catch (BatchUpdateException bue) {
updateCountsConsumer.accept(bue.getUpdateCounts());
bue.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
- 生成键
// 执行SQL,并指定是否返回自动生成的键
// autoGeneratedKeys:
// Statement.RETURN_GENERATED_KEYS(1)
// Statement.NO_GENERATED_KEYS(2)
int executeUpdate(String sql, int autoGeneratedKeys);
// columnIndexes指定返回的自动生成键
int executeUpdate(String sql, int columnIndexes[]);
// columnNames指定返回的自动生成键
int executeUpdate(String sql, String columnNames[]);
// 返回:
// true,第一个结果是ResultSet
boolean execute(String sql, int autoGeneratedKeys);
boolean execute(String sql, int columnIndexes[]);
boolean execute(String sql, String columnNames[]);
ResultSet getGeneratedKeys();
例:
String sql = "INSERT INTO user(userName, nickName, status, createTime, updateTime)VALUES" +
"('[email protected]', '测试', 0, unix_timestamp()*1000, unix_timestamp()*1000)";
int updateCount = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
System.out.println("更新:" + updateCount);
ResultSet resultSet = statement.getGeneratedKeys();
while (resultSet.next()) {
// 列名为GENERATED_KEY
long id = resultSet.getLong(1);
System.out.println("键:" + id);
}
resultSet.close();
- 关闭
void close();
PreparedStatement
预编译SQL语句,可以动态设置参数,多次执行。继承Statement。
- 参数,参数序号1起
// 设置null
// sqlType:java.sql.Types
void setNull(int parameterIndex, int sqlType);
void setBoolean(int parameterIndex, boolean x);
void setInt(int parameterIndex, int x);
void setObject(int parameterIndex, Object x);
void setObject(int parameterIndex, Object x, int targetSqlType);
...
// 清除参数
void clearParameters();
// 查询参数信息
ParameterMetaData getParameterMetaData();
- 查询
ResultSet executeQuery();
例:
String sql = "select * from user where userName = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "[email protected]");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
// 列标
long userId = resultSet.getLong("id");
String userName = resultSet.getString("userName");
String nickName = resultSet.getString("nickName");
System.out.println(userId + " " + userName + " " + nickName);
}
resultSet.close();
preparedStatement.close();
- 更新
int executeUpdate();
- 多结果(同Statement)
// 执行任何类型SQL
boolean execute();
- 批量更新
void addBatch();
ParameterMetaData
对于某些驱动,需要在PreparedStatement执行后才能获取参数信息。
// 参数数量
int getParameterCount();
// 参数类型,参数序号1起
int getParameterType(int param);
// 参数类型名称
String getParameterTypeName(int param);
// 参数类型对应的Java类名
String getParameterClassName(int param);
// 参数模式
// 返回:
// ParameterMetaData.parameterModeIn
// ParameterMetaData.parameterModeOut
// ParameterMetaData.parameterModeInOut
// ParameterMetaData.parameterModeUnknown
int getParameterMode(int param);
CallableStatement
用于执行SQL存储过程。继承PreparedStatement。
IN参数值使用set方法设置,OUT参数registerOut方法注册。参数序号1起。
ResultSet按Statement方式获取。
- 设置IN参数
void setString(String parameterName, String x);
void setBoolean(String parameterName, boolean x);
...
- 注册OUT参数
// sqlType: java.sql.Types
void registerOutParameter(int parameterIndex, int sqlType);
void registerOutParameter(int parameterIndex, int sqlType, int scale);
void registerOutParameter(String parameterName, int sqlType);
void registerOutParameter(String parameterName, int sqlType, int scale);
void registerOutParameter (String parameterName, int sqlType, String typeName);
- 获取OUT结果
String getString(int parameterIndex);
boolean getBoolean(int parameterIndex);
...
- 例子
- 存储过程
// 改结束符,为$$
mysql> delimiter $$
// 创建存储过程
mysql> create procedure getUser(INOUT p_u varchar(128), IN p_s tinyint(4), OUT p_i bigint(20))
begin
// 赋值给OUT变量p_i,p_u
SELECT id, nickName INTO p_i, p_u
FROM user
WHERE userName = p_u AND status = p_s;
end$$
- 调用存储过程
// 赋值系统变量
mysql> set p_userName='[email protected]'$$
// 调用存储过程,将OUT变量赋值给系统变量
mysql> call getUser(@p_userName, 0, @p_id)$$
// 查询系统变量
mysql> select @p_userName$$
// 查询系统变量
mysql> select @p_id$$
- Java Code
// 存储过程getUser(INOUT, IN, OUT)
String sql = "call getUser(?, ?, ?)";
CallableStatement callableStatement = connection.prepareCall(sql);
// 设置IN参数p_u
callableStatement.setString(1, "[email protected]");
// 设置IN参数p_s
callableStatement.setInt(2, 0);
// 注册OUT参数p_u
callableStatement.registerOutParameter(1, Types.VARCHAR);
// 注册OUT参数p_i
callableStatement.registerOutParameter(3, Types.BIGINT);
// 执行
callableStatement.execute();
// 获取OUT结果p_u
String nickName = callableStatement.getString(1);
// 获取OUT结果p_i
long userId = callableStatement.getLong(3);
System.out.println("userId = " + userId + ", nickName = " + nickName);
callableStatement.close();