API解读第三篇——处理结果集的核心对象(JDBC)

核心对象

处理结果集的核心对象有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

时间: 2024-08-20 17:59:50

API解读第三篇——处理结果集的核心对象(JDBC)的相关文章

跟我学习SpringCloud 教程第三篇:注册中心集群篇-b2b2c小程序电子商务

集群环境搭建?了解springcloud架构可以加求求:三五三六二四七二五九第一步:我们新建两个注册中心工程一个叫eureka_register_service_master.另外一个叫eureka_register_service_backup eureka_register_service_master的application.properties配置如下?server.port=7998 eureka.client.register-with-eureka=false eureka.cli

API开发第三篇:PHP的设计模式之完美的单例模式

今天来说一说单例模式. 由于我以前是做java开发的,在使用单例模式的时候,首先想到的想用饿汉式,然后发现在PHP中,有这样一个特性:因为PHP不支持在类定义时给类的成员变量赋予非基本类型的值.如表达式,new操作等等.所以了饿汉式这个就不行了.转而想要确保这个单例模式的原子性,发现PHP中也没有像JAVA中的线程安全问题.嘿嘿,你说PHP好不好?那么OK接下来就试试PHP的懒汉式单例模式了. 先不说,我先上我第一个版本的单例模式代码: // 定义私有静态变量.此种方式为:懒汉式单例(PHP中只

API解读第一篇——建立连接的核心对象(JDBC)

结构图 核心对象 Driver Java通过Driver接口表示驱动,每种类型的数据库通过实现Driver接口提供自己的Driver实现类. Driver由属性,操作,事件三部分组成. 属性 公共属性 版本号:版本号由两个字段主版本号(majorVersion)和副版本号(minorVersion)组成. 特殊属性: DriverPropertyInfo对象:它有四个字段,name表示属性名称,value表示属性值,required.表示是否是必要属性,description表示对属性的描述.

API解读第二篇——执行SQL的核心对象(JDBC)

结构图 核心对象 Statement Statement主要用来执行SQL语句.它执行SQL语句的步骤为: 第一步:创建statement对象. 第二步:配置statement对象,此步骤可以忽略. 第三步:调用statement的executeXXX方法执行SQL语句. 第四步:处理结果集.示例中只是打印结果集. 第五步:关闭statement对象. Statement执行SQL语句的方法有四种类型. execute执行返回结果包含一个或者多个结果集,或结果包含一个或多个更新记录数量的SQL语

从零开始学习jQuery (三) 管理jQuery包装集

本系列文章导航 从零开始学习jQuery (三) 管理jQuery包装集 一.摘要 在使用jQuery选择器获取到jQuery包装集后, 我们需要对其进行操作. 本章首先讲解如何动态的创建元素, 接着学习如何管理jQuery包装集, 比如添加,删除,切片等. 二.前言 本系列的2,3篇上面列举了太多的API相信大家看着眼晕. 不过这些基础还必须要讲, 基础要扎实.其实对于这些列表大家可以跳过, 等以后用到时再回头看或者查询官方的API说明. 本章内容很少, 主要讲解动态创建元素和操作jQuery

PHP 性能分析第三篇: 性能调优实战

注意:本文是我们的 PHP 性能分析系列的第三篇,点此阅读 PHP 性能分析第一篇: XHProf & XHGui 介绍 ,或  PHP 性能分析第二篇: 深入研究 XHGui. 在本系列的 第一篇 中,我们介绍了 XHProf .而在 第二篇 中,我们深入研究了 XHGui UI, 现在最后一篇,让我们把 XHProf /XHGui 的知识用到工作中! 性能调优 不用运行的代码才是绝好的代码.其他只是好的代码.所以,性能调优时,最好的选择是首先确保运行尽可能少的代码. OpCode 缓存 首先

SignalR循序渐进(三)简易的集群通讯组件

上一篇演示了泛型Hub的实现,微软于6月17日更新了SignalR 2.1.0,然后自带了泛型Hub,于是就不需要自己去实现了…(微软你为啥不早一个月自带啊…).不过没关系,SignalR出彩之处不在泛型Hub,本篇为各位观众带来了基于SignalR的简易集群通讯组件Demo,可用于分布式定时任务. 说到集群,自然想到了NLB啊Cluster啊HPC啊等等.NLB受制于成员数量,Cluster用数量堆高可用性,HPC太复杂.本着SignalR的双向异步通讯的特点,其实是可以用来玩弹性计算的.初始

LoadRunner用户行为模拟器 《第三篇》

用户行为模拟器简称VU,VU通过运行VU脚本模拟了用户对软件的操作行为.VU是基于网络协议的.很明显,被测服务器是通过各种各样的网络协议与客户端打交道的.VU要"骗过"被测服务器,当然就要遵守这些协议,按规矩.按步骤来执行动作,否则就会吃"闭门羹". 基于网络协议的脚本的一个好处是,我们可以使用相对少的硬件资源,来生成大量的虚拟用户负载.相比之下,WinRunner和QTP脚本时基于界面事件的,它在一台主机上同时只能运行一个虚拟用户的脚本,因为一个虚拟用户会占用整个

SQL Server索引的维护 - 索引碎片、填充因子 &lt;第三篇&gt;

实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多),一个区中的页面可能属于多余一个的索引或表---这被称为混合区.如果数据库中有太多的小表,混合区帮助SQL Server节约磁盘空间. 随着表(或索引)增长并且请求超过8个页面,SQL Server创建专用于该表(或索引)的区并且从该区中分配页面.这样一个区被称为统一区,它可以为多达8个相同表或索引的