Java JDBC 4
2019-02-01 本文已影响0人
毛小力
ResultSet
表示数据库查询结果的数据表。
ResultSet对象有一个光标指向当前数据行。最初,光标位于第一行之前,next方法将光标移动到下一行,没有更多行(最后一行之后)时返回false。
默认,光标只能向前移动,只能从第一行移动到最后一行,且只能遍历一次。可以生成可滚动的ResultSet。
ResultSet提供getter方法,通过列号(1起,更高效)或列名(不区分大小写),从当前行获取列值。为可移植性,最好按从左到右的顺序获取列值,且每列只读取一次。
- ResultSet属性
// ResultSetType
// 返回:
// ResultSet.TYPE_FORWARD_ONLY(默认,1003):光标只能向前
// ResultSet.TYPE_SCROLL_INSENSITIVE(1004):光标可滚动,对底层数据变化不敏感
// ResultSet.TYPE_SCROLL_SENSITIVE(1005):光标可滚动,对底层数据变化敏感
int getType();
// ResultSetConcurrency
// 返回:
// ResultSet.CONCUR_READ_ONLY(默认,1007):只读
// ResultSet.CONCUR_UPDATABLE(1008):可更新
int getConcurrency();
// ResultSetHoldability
// 返回:
// ResultSet.HOLD_CURSORS_OVER_COMMIT(1):当前事务提交后ResultSet仍打开
// ResultSet.CLOSE_CURSORS_AT_COMMIT(2):当前事务提交后ResultSet关闭
int int getHoldability();
// 光标移动方向
// 返回:
// ResultSet.FETCH_FORWARD(默认,1000)
// ResultSet.FETCH_REVERSE(1001)
// ResultSet.FETCH_UNKNOWN(1002)
int getFetchDirection();
void setFetchDirection(int direction);
// 一次读取的行数,0表示忽略
int getFetchSize();
void setFetchSize(int rows);
- 操作光标
// 移动到下一行
// 返回:是否指向有效行
boolean next();
// 移动到上一行
// 返回:是否指向有效行
boolean previous();
// 移动到第一行之前
void beforeFirst();
// 移动到最后一行之后
void afterLast();
// 是否在第一行之前
boolean isBeforeFirst();
// 是否在最后一行之后
boolean isAfterLast();
// 移动到第一行
// 返回:是否指向有效行
boolean first();
// 移动到最后一行
// 返回:是否指向有效行
boolean last();
// 是否在第一行
boolean isFirst();
// 是否在最后一行
boolean isLast();
// 当前行号,1起
int getRow();
// 移动到第row行
boolean absolute(int row);
// rows正:向前移动rows行,等同rows次next(),到最后一行之后为止
// rows负:向后移动|rows|行,等同|rows|此previous(),到第一行之前为止
boolean relative(int rows);
- 获取列信息
ResultSetMetaData getMetaData();
ResultSetMetaData:
// 列数
int getColumnCount();
// 列名,AS之前
// column,1起
String getColumnName(int column);
// 列标,AS之后
// 若没有使用AS则与列名相同
String getColumnLabel(int column);
// 列类型,见java.sql.Types
int getColumnType(int column);
// 列类型名
String getColumnTypeName(int column);
// 列类型映射的Java类型
String getColumnClassName(int column);
// 自增列
boolean isAutoIncrement(int column);
实例:
Connection connection = DriverManager.getConnection(url);
Statement statement = connection.createStatement();
String sql = "select *, id as userId from user";
ResultSet resultSet = statement.executeQuery(sql);
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
System.out.println("列数:" + columnCount);
for (int i = 1; i <= columnCount; i++) {
String label = metaData.getColumnLabel(i);
String name = metaData.getColumnName(i);
int type = metaData.getColumnType(i);
String typeName = metaData.getColumnTypeName(i);
String className = metaData.getColumnClassName(i);
boolean isAutoIncrement = metaData.isAutoIncrement(i);
System.out.println(label + ", " + name + ", " + type + ", " + typeName + ", " + className + ", " + isAutoIncrement);
}
resultSet.close();
statement.close();
connection.close();
- 获取列值
// 通过列号获取列值
String getString(int columnIndex);
boolean getBoolean(int columnIndex);
...
// 通过列名获取列值
String getString(String columnLabel);
boolean getBoolean(String columnLabel);
...
// 列名对应的列号
int findColumn(String columnLabel);
实例:
private static Consumer<ResultSet> getRowValue = rs -> {
try {
long userId = rs.getLong("id");
String userName = rs.getString("userName");
String nickName = rs.getString("nickName");
Timestamp timestamp = rs.getTimestamp("dbUpdateTime");
System.out.println(userId + " " + userName + " " + nickName + " " + timestamp);
} catch (SQLException e) {
e.printStackTrace();
}
};
Connection connection = DriverManager.getConnection(url);
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
String sql = "select *, id as userId from user";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
getRowValue.accept(resultSet);
}
System.out.println("isAfterLast: " + resultSet.isAfterLast());
while (resultSet.previous()) {
getRowValue.accept(resultSet);
}
System.out.println("isBeforeFirst: " + resultSet.isBeforeFirst());
if (resultSet.absolute(1)) {
getRowValue.accept(resultSet);
}
System.out.println("currentRow: " + resultSet.getRow());
resultSet.close();
statement.close();
connection.close();
- 关闭
// 是否已关闭
boolean isClosed();
void close();
- 感知更新
// 当前行是否被更新
// SQLFeatureNotSupportedException:不支持该方法
// DatabaseMetaData.updatesAreDetected():查看是否支持
boolean rowUpdated();
// DatabaseMetaData.insertsAreDetected():查看是否支持
boolean rowInserted();
// DatabaseMetaData.deletesAreDetected():查看是否支持
boolean rowDeleted();
// 从DB更新当前行
void refreshRow();
- 更新
有两种方式进行更新:
更新行
rs.absolute(5); // 移动到指定行
rs.updateString("NAME", "AINSWORTH"); // 更新列值
rs.updateRow(); // 更新行插入行
rs.moveToInsertRow(); // 移动到插入行(构建要插入的行的暂存区)
rs.updateString(1, "AINSWORTH"); // 设置列值
rs.insertRow(); // 插入行
rs.moveToCurrentRow(); // 返回到插入前的数据行
// 移动到插入行
void moveToInsertRow();
// 设置当前行列值
void updateString(int columnIndex, String x);
void updateBoolean(int columnIndex, boolean x);
...
// 取消当前行列值的设置
void cancelRowUpdates();
// 将插入行更新到DB
void insertRow();
// 返回到插入前的数据行
void moveToCurrentRow();
// 更新当前行到DB
void updateRow();
// 删除当前行到DB
void deleteRow();
实例:
Connection connection = DriverManager.getConnection(url);
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
String sql = "select *, id as userId from user";
ResultSet resultSet = statement.executeQuery(sql);
resultSet.moveToInsertRow();
resultSet.updateString("userName", "lmztest@163.com");
resultSet.updateString("nickName", "测试插入");
resultSet.updateInt("status", 0);
resultSet.updateLong("createTime", System.currentTimeMillis());
resultSet.updateLong("updateTime", System.currentTimeMillis());
resultSet.insertRow();
ThreadUtil.sleepSeconds(10);
while (resultSet.next()) {
String userName = resultSet.getString("userName");
if (userName.endsWith("lmztest@163.com")) {
System.out.println("CurrentRow: " + resultSet.getRow());
break;
}
}
resultSet.updateInt("status", 3);
resultSet.updateRow();
ThreadUtil.sleepSeconds(10);
resultSet.deleteRow();
resultSet.close();
statement.close();
connection.close();
- 流式读取(一次一行):MySQL
- ResultSetType: TYPE_FORWARD_ONLY
- ResultSetConcurrency: CONCUR_READ_ONLY
- FetchSize: Integer.MIN_VALUE
Connection connection = DriverManager.getConnection(MYSQL_URL);
Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
statement.setFetchSize(Integer.MIN_VALUE);
//
// resultSet.rowData为类RowDataDynamic
ResultSet resultSet = statement.executeQuery("select * from user order by id");
while (resultSet.next()) {
getRowValue.accept(resultSet);
}
resultSet.close();
statement.close();
connection.close();
- 游标读取(一次多行):MySQL
- useCursorFetch: true
- ResultSetType: TYPE_FORWARD_ONLY
- FetchSize: 大于0
Properties properties = new Properties();
properties.setProperty("useCursorFetch", "true");
Connection connection = DriverManager.getConnection(MYSQL_URL, properties);
Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
statement.setFetchSize(5);
// resultSet.rowData为类RowDataCursor
ResultSet resultSet = statement.executeQuery("select * from user order by id");
while (resultSet.next()) {
getRowValue.accept(resultSet);
}
resultSet.close();
statement.close();
connection.close();