核心对象

处理结果集的核心对象有ResultSet和RowSet。其中ResultSet指定关系型数据库的结果集,RowSet更为抽象,凡是由行列组成的数据都可以。

ResultSet

ResultSet对象的主要作用是获取数据库中的查询结果。它主要由三部分组成,查询结果与结果集对象的关系,结果集对象的类型,结果集对象的操作。

关系

每个结果集与查询结果一一对应的关系,结果集包含查询结果中的全部列,但只包含查询结果中的某些行。如果查询结果是跨表的,那么结果集也是跨表的,这种类型的结果集无法进行更新,插入操作。

要获取结果集中的对象,如果了解查询结果的列名称以及该列的数据类型,可以通过名称来获取数据的值,如果了解查询结果中列的顺序以及每列对应的数据类型,可以通过索引来获取数据的值。 如果不了解查询结果的结构,可以通过获取ResultSetMetaData对象来获取查询结果中的相关信息。

ResultSetMetaData

ResultSetMetaData包含查询结果的相关信息,大体可以分为四类。

数据库

// 一个catalog包含多个schema,一个schema包含多张table,查询结果集可以来自多张表
System.out.println("查询结果第" + i + "列的Catalog名称:" + rsMetaData.getCatalogName(i));
System.out.println("查询结果第" + i + "列的shcema名称:" + rsMetaData.getSchemaName(i));
System.out.println("查询结果第" + i + "列的table名称:" + rsMetaData.getTableName(i));

列的信息

// 列信息,获取列的名称,类型
System.out.println("查询结果第" + i + "列名:" + rsMetaData.getColumnName(i));
System.out.println("查询结果第" + i + "列label:" + rsMetaData.getColumnLabel(i));
System.out.println("查询结果第" + i + "列的type名称:" + rsMetaData.getColumnType(i));
System.out.println("查询结果第" + i + "列的数据库数据类型:" + rsMetaData.getColumnTypeName(i));
System.out.println(
"查询结果第" + i + "列的columnDisplaySize:" + rsMetaData.getColumnDisplaySize(i));
System.out.println("查询结果第" + i + "列对应的java数据类型:" + rsMetaData.getColumnClassName(i));

列的特性

// 列的特性,例如是否为null.
System.out.println("查询结果第" + i + "列是否允许空值:" + rsMetaData.isNullable(i));
System.out.println("查询结果第" + i + "列是否为货币:" + booleanToStr(rsMetaData.isCurrency(i)));
System.out.println(
"查询结果第" + i + "列是否是自增列:" + booleanToStr(rsMetaData.isAutoIncrement(i)));
System.out.println(
"查询结果第" + i + "列是否是大小写敏感:" + booleanToStr(rsMetaData.isCaseSensitive(i)));

权限

// 列的权限
System.out.println(
"查询结果第" + i + "列是否拥有写权限:" + booleanToStr(rsMetaData.isDefinitelyWritable(i)));
System.out.println("查询结果第" + i + "列是否只读权限:" + booleanToStr(rsMetaData.isReadOnly(i)));
System.out.println("查询结果第" + i + "列是否允许搜索:" + booleanToStr(rsMetaData.isSearchable(i)));

类型

结果集的类型可以通过设置其同步方式,遍历方式,关闭方式来指定。

/**
* 打印结果集类型相关信息,设置结果集类型信息是在创建Statement相关对象时指定。ResultSet本身并没有这些方法
* 输出结果需要参考Java API Constant Field Values
* @param rs
* @throws SQLException
*/
public static void printResultTypeInfo(ResultSet rs) throws SQLException {
System.out.println("-------------------结果集的类型相关信息-------------------");
System.out.println("结果集的遍历类型:" + rs.getType());
System.out.println("结果集的同步类型:" + rs.getConcurrency());
System.out.println("结果集的关闭方式:" + rs.getHoldability());
}

 同步方式

  1. CONCUR_READONLY:结果集是只读的,只能进行遍历操作。用户读数据时会获取read锁,这也是默认的方式
  2. CONCUR_UPDATABLE:结果集是可以更新的,用户读取数据时会获取read-write锁,当对数据库进行插入,更新,删除操作时,存在两种锁机制,悲观锁和乐观锁。悲观锁只允许单个用户访问数据,只有当前用户释放锁之后,其他用户才可以进行访问。乐观锁允许多个用户同时对数据进行访问,当发生冲突时,会回滚之后造成冲突的事务,以此来保证数据的完整性。

遍历方式

  1. FORWARD_ONLY:只能从前往后遍历1
  2. TYPE_SCROLL_SENSITIVE:结果集是可滚动的,可以从前到后,也可以从后到前遍历,也可以指定从任意的位置开始遍历,但是结果集中的数据在创建时已经指定,如果查询结果发生改变,结果集中的数据不会感应改变。
  3. TYPE_SCROLL_INSENSITIVE:结果集是可以滚动的,遍历方式是任意的,查询结果发生改变时,结果集中会包含新的查询结果。

 关闭方式

  1. CLOSE_CURSORS_AT_COMMIT:当事务提交时,会关闭结果集对象
  2. HOLD_CURSORS_OVER_COMMIT:当事务提交时,不会关闭结果集对象。

操作

遍历

结果集遍历的方式有四种,从前到后,从后到前,指定绝对位置,相对位置。默认的结果集是FORWARD_ONLY类型,只能从前到后遍历,其他遍历方式需要将结果集设置为TYPE_SCROLL_SENSITIVE或TYPE_SCROLL_INSENSITIVE。

从前到后

/**
* 遍历结果集对象从前到后
*
* @param rs
* @throws SQLException
*/
private static void printTopToBottom(ResultSet rs) throws SQLException {
rs.beforeFirst();
while (rs.next()) {
System.out.print("学生的姓名为:" + rs.getString(1) + "\t");
System.out.print("学生的学号为:" + rs.getInt(2) + "\t");
System.out.print("学生的班级为: " + rs.getString(3) + "\t");
System.out.print("学生的课程为:" + rs.getString(4) + "\t");
System.out.println("学生的生日为:" + rs.getDate(5) + "\t");
}
}

从后到前

/**
* 遍历结果集对象,从后到前
*
* @param rs
* @throws SQLException
*/
private static void printBottomToTop(ResultSet rs) throws SQLException {
rs.afterLast();
while (rs.previous()) {
System.out.print("学生的姓名为:" + rs.getString(1) + "\t");
System.out.print("学生的学号为:" + rs.getInt(2) + "\t");
System.out.print("学生的班级为: " + rs.getString(3) + "\t");
System.out.print("学生的课程为:" + rs.getString(4) + "\t");
System.out.println("学生的生日为:" + rs.getDate(5) + "\t");
}
}

绝对位置

/**
* 遍历结果集,使用绝对方式
*
* @param rs
* @param pos 从第几行开始,起始值为1
* @throws SQLException
*/
private static void printByAbsolutePos(ResultSet rs, int pos) throws SQLException {
rs.absolute(pos);
while (rs.next()) {
System.out.print("学生的姓名为:" + rs.getString(1) + "\t");
System.out.print("学生的学号为:" + rs.getInt(2) + "\t");
System.out.print("学生的班级为: " + rs.getString(3) + "\t");
System.out.print("学生的课程为:" + rs.getString(4) + "\t");
System.out.println("学生的生日为:" + rs.getDate(5) + "\t");
}
}

相对位置

/**
* 遍历结果集,使用相对位置
*
* @param rs
* @param pos
* @throws SQLException
*/
private static void printByRelativePos(ResultSet rs, int pos) throws SQLException {
// 指定到最后一行
rs.last();
// 结果集条数
int total = rs.getRow();
// 指定到第一行
rs.beforeFirst();
while (rs.next()) {
// 判断当前行从前或从后移动pos位置后没有超过越界
if (rs.getRow() + pos < total) {
rs.relative(pos);
}
System.out.print("学生的姓名为:" + rs.getString(1) + "\t");
System.out.print("学生的学号为:" + rs.getInt(2) + "\t");
System.out.print("学生的班级为: " + rs.getString(3) + "\t");
System.out.print("学生的课程为:" + rs.getString(4) + "\t");
System.out.println("学生的生日为:" + rs.getDate(5) + "\t");
}
}

更新

结果集更新数据同步到数据库中需要如下前提条件:

  1. 结果集的类型为CONCUR_UPDATEABLE。
  2. 结果集包含的数据是单张表中的数据
  3. 结果集对应的查询语句不能包含join,group by 和* 号
  4. 结果集中包含主键字段
/**
* 结果集中更新数据,同步到数据库当中。
* 前提条件:
* 1.结果集类型为CONCUR_UPDATABLE
* 2.结果集中的对象是单表,
* 3.结果集对应的查询不包含join和group by 语句,不能包含*号
* 4.结果集中包含主键字段
*
* @param rs
* @throws SQLException
*/
public static void updateData(ResultSet rs) throws SQLException
{
// 演示更新最后一条数据
rs.last();
// 更新姓名
rs.updateString(1, "更新之后的名称");
// 更新学号
rs.updateInt(2, 500);
// 更新班级
rs.updateString(3, "更新之后的班级");
// 更新课程
rs.updateString(4, "更新之后的课程");
// 更新生日
rs.updateDate(5, new Date(2017, 11, 12));
// 更新结果集和数据库
rs.updateRow();
}

插入

结果集插入数据除了需要满足更新时的条件外,还需要满足如下条件

  1. 用户对该表拥有权限
  2. 结果集包含所有插入时不为null值的列
/**
* 结果集插入数据,同步到数据库当中。
* 在更新操作的前提下,还有额外的要求
* 1.用户对该表有读写的权限
* 2.结果集中包含所有不允许非空的列
* @param rs
* @throws SQLException
*/
public static void insertData(ResultSet rs) throws SQLException
{
// 准备插入一条数据
rs.moveToInsertRow();
// 插入姓名
rs.updateString(1, "插入的名称");
// 插入学号
rs.updateInt(2, 501);
// 插入班级
rs.updateString(3, "插入的班级");
// 插入课程
rs.updateString(4, "插入的课程");
// 插入生日
rs.updateDate(5,new Date(2017,11,12));
// 插入数据,因为达到了最大条数限制,所以结果集中不包含刚插入的数据,但是从数据库中可以查询得到
rs.insertRow();
}

删除

/**
* 结果集中删除某一行
* @param rs
* @throws SQLException
*/
public static void deleteData(ResultSet rs) throws SQLException
{
// 删除结果集
rs.last();
rs.deleteRow();
}

ROWSET

TODO

数据库程序接口——JDBC——API解读第三篇——处理结果集的核心对象的更多相关文章

  1. 数据库程序接口——JDBC——API解读第一篇——建立连接的核心对象

    结构图 核心对象 Driver Java通过Driver接口表示驱动,每种类型的数据库通过实现Driver接口提供自己的Driver实现类. Driver由属性,操作,事件三部分组成. 属性 公共属性 ...

  2. 数据库程序接口——JDBC——API解读第二篇——执行SQL的核心对象

    结构图 核心对象 Statement Statement主要用来执行SQL语句.它执行SQL语句的步骤为: 第一步:创建statement对象. 第二步:配置statement对象,此步骤可以忽略. ...

  3. 数据库程序接口——JDBC——初篇——目录

    目录 建立连接 核心对象 Driver DriverManager Connection DataSource 常用功能 第一个程序 C3P0数据源 DBCP数据源 事务之Spring事务 执行SQL ...

  4. 数据库程序接口——JDBC——功能第四篇——事务之Spring事务

    综述 事务的实现方式有三种,JTA,Spring事务,Web Container方式.本篇讲述Spring事务. Spring事务分为两个部分核心对象,Spring事务的实现方式. Spring事务实 ...

  5. 数据库程序接口——JDBC——功能第一篇——第一个程序

    流程图 综述 从零开始搭建JDBC环境.通过创建Java项目,在项目中,通过java程序执行SQL,并处理返回的结果.本文通过执行 select 1 from dual 语句来测试,并输出相结果集.首 ...

  6. 数据库程序接口——JDBC——功能第二篇——数据源之C3P0数据源

    综述 C3P0由三部分内容组成.实例化对象,各配置项的含义,以及加载配置项的方式. 实例化对象的方式有三种,第一种方式直接new ComboPooledDataSource,第二种方式使用工厂类Dat ...

  7. 数据库程序接口——JDBC——功能第五篇——批量处理

    综述 批量处理一般指批量插入,批量更新,删除通过可以指定where条件实现.批量插入的实现方式有三种类型.statement,preparedStatement,callableStatement. ...

  8. 深入理解javascript选择器API系列第三篇——h5新增的3种selector方法

    × 目录 [1]方法 [2]非实时 [3]缺陷 前面的话 尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展.人们对jQuer ...

  9. 深入理解javascript选择器API系列第三篇——HTML5新增的3种selector方法

    前面的话 尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展.人们对jQuery的称赞,很多是由于jQuery方便的元素选择器 ...

随机推荐

  1. springBoot 发送邮件图片不显示

    解决方案 MimeMessageHelper 的执行顺序错了,先执行 setText() 然后执行 addInline() 添加图片 <img src="cid:p03"/& ...

  2. 解决myeclipse2017ci7破解后闪退问题

    解决myeclipse2017ci7破解后闪退问题 打开myeclipse.ini修改为: #utf8 (do not remove)-startupplugins/org.eclipse.equin ...

  3. Redis 数据总结(1 数据导入)

    理论基础部分:http://www.redis.cn/topics/mass-insert.html 几百上千万的数据建议使用pipe来完成导入. 1.windows 下数据导入命令: type ou ...

  4. How to write a paper in a weekend - by Prof. Pete Carr

    Key points: don't procrastinate; review the notes and renew the literature search; determine who you ...

  5. phpstorm实现分屏展示代码

    第一种 选择你要分屏的页面 [Window]—>[Editor Tabs]—>[Split Vertically]or[Split Horizontally]  第二种 把鼠标箭头放到你想 ...

  6. [转]JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  7. 二分-F - Aggressive cows

    F - Aggressive cows Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. ...

  8. TensorFlow 2.0高效开发指南

    Effective TensorFlow 2.0 为使TensorFLow用户更高效,TensorFlow 2.0中进行了多出更改.TensorFlow 2.0删除了篇冗余API,使API更加一致(统 ...

  9. Go生成随机数

    生成随机数 概念 伪随机数,都是根据一定的算法公式算出来的. 所在包 math/rand 生成随机数的公式需要一个种子数,一般为整数.种子数相同会导致每次启动程序是生成随机数相同,为了避免重复每次生成 ...

  10. AcWing 1018. 最低通行费

    #include<iostream> using namespace std ; ,INF=1e9; int dp[N][N],w[N][N]; int n; int main() { c ...