Java JDBC 3

Statement

用于执行静态SQL并返回结果对象。
默认情况下,每个Statement对象只能有一个ResultSet对象同时打开。如果打开ResultSet则会隐式关闭当前ResultSet对象。

  1. 属性
// 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();
  1. 查询
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();
  1. 更新
// 返回影响行数
int executeUpdate(String sql);
  1. 多结果
// 执行给定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();
}
  1. 批量更新
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<int[]> updateCountsConsumer = new Consumer<int[]>() {
    @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();
}
  1. 生成键
// 执行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();
  1. 关闭
void close();

PreparedStatement

预编译SQL语句,可以动态设置参数,多次执行。继承Statement。

  1. 参数,参数序号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();
  1. 查询
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();
  1. 更新
int executeUpdate();
  1. 多结果(同Statement)
// 执行任何类型SQL
boolean execute();
  1. 批量更新
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方式获取。

  1. 设置IN参数
void setString(String parameterName, String x);
void setBoolean(String parameterName, boolean x);
...
  1. 注册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);
  1. 获取OUT结果
String getString(int parameterIndex);
boolean getBoolean(int parameterIndex);
...
  1. 例子
  • 存储过程
// 改结束符,为$$
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();

猜你喜欢

转载自blog.csdn.net/weixin_34248023/article/details/86938785